DRIP supports two distinct types of API clients, each designed for different use cases. Understanding the difference is crucial for choosing the right approach for your integration.

Client Type Overview

Realm Clients

Purpose: Direct access to your own realm
Scope: Single realm only
Authorization: Automatic access to your realm
Best for: Internal tools, custom dashboards, automation

App Clients

Purpose: Multi-realm applications
Scope: Multiple realms with explicit authorization
Authorization: Publish + per-realm authorization
Best for: Third-party integrations, marketplace apps

When to Use Each Type

Use Realm Clients When:

  • Building tools for your own community only
  • Creating internal dashboards or analytics
  • Automating tasks within your realm
  • Developing custom member management tools
  • You need immediate access without approval processes

Use App Clients When:

  • Building apps for multiple communities
  • Creating marketplace applications
  • Developing SaaS tools for DRIP communities
  • Building integrations that other realms can install
  • You want to distribute your app publicly

Creating API Clients

Creating a Realm Client

1

Access Developer Portal

Navigate to AdminDeveloper in your DRIP dashboard
2

Go to Project API

Click the Project API tab
3

Create Client

Click Create API Client and configure:
  • Name: Descriptive name for your integration
  • Scopes: Select the permissions you need
4

Save Credentials

Copy and securely store your Client Secret (this is your API key)

Creating an App Client

1

Access Developer Portal

Navigate to AdminDeveloper in your DRIP dashboard
2

Go to DRIP Apps

Click the DRIP Apps tab
3

Set up New App

In the Listing section, you can set up your app metadata (name, description, logo)
4

Get App Client

In the App Client section, you can set up your app client credentials
5

Submit App

Once your app is ready, you can publish it to the DRIP Apps marketplace
6

Wait for Approval

DRIP reviews your app for security and compliance

Scope Management

Understanding Scopes

Scopes define what your client can access and modify.
For apps: you select the scopes your app needs. Realms/projects grant those scopes when they authorize your app. If you later change your app’s requested scopes, realms must reauthorize for the new scopes to take effect.

Basic Scopes

const basicScopes = [
  'realm:read',           // Read realm information
  'members:read',         // Read member profiles
  'quests:read',          // Read quest data
  'store:read',           // Read store items
];

Advanced Scopes

const advancedScopes = [
  'members:write',        // Modify member data
  'points:write',         // Award/deduct points
  'quests:write',         // Create/modify quests
  'store:write',          // Manage store items
];

Scope Selection Best Practices

Authorization Flows

Realm Client Flow

Characteristics:
  • ✅ Immediate access
  • ✅ No approval delays
  • ✅ Full permissions within your realm
  • ❌ Limited to single realm
  • ❌ Can’t be distributed to other realms

App Client Flow

Characteristics:
  • ✅ Multi-realm capability
  • ✅ Can be distributed publicly
  • ✅ Scalable business model
  • ❌ Requires platform approval
  • ❌ Each realm must authorize separately
  • ❌ Limited to approved scopes only

Managing Multiple Clients

Client Organization

class DripClientManager {
  constructor() {
    this.clients = new Map();
  }

  // Add a realm client
  addRealmClient(name, apiKey, realmId) {
    this.clients.set(name, {
      type: 'realm',
      client: new DripClient(apiKey, realmId),
      realmId
    });
  }

  // Add an app client
  addAppClient(name, appClientSecret) {
    this.clients.set(name, {
      type: 'app',
      client: new DripAppClient(appClientSecret),
      authorizedRealms: []
    });
  }

  // Get client by name
  getClient(name) {
    return this.clients.get(name);
  }

  // List all clients
  listClients() {
    return Array.from(this.clients.entries()).map(([name, config]) => ({
      name,
      type: config.type,
      realmId: config.realmId || 'multiple'
    }));
  }
}

// Usage
const manager = new DripClientManager();
manager.addRealmClient('analytics', 'realm_api_key', 'realm_id');
manager.addAppClient('marketplace-app', 'app_client_secret');

Environment-Based Configuration

// config/clients.js
const clients = {
  development: {
    realm: {
      apiKey: process.env.DEV_REALM_API_KEY,
      realmId: process.env.DEV_REALM_ID
    },
    app: {
      clientSecret: process.env.DEV_APP_CLIENT_SECRET
    }
  },
  production: {
    realm: {
      apiKey: process.env.PROD_REALM_API_KEY,
      realmId: process.env.PROD_REALM_ID
    },
    app: {
      clientSecret: process.env.PROD_APP_CLIENT_SECRET
    }
  }
};

const env = process.env.NODE_ENV || 'development';
export const realmClient = new DripClient(
  clients[env].realm.apiKey,
  clients[env].realm.realmId
);
export const appClient = new DripAppClient(
  clients[env].app.clientSecret
);

Security Best Practices

API Key Management

Secure Storage

  • Store keys in environment variables
  • Use secure key management services
  • Never commit keys to version control
  • Rotate keys regularly

Access Control

  • Use least-privilege scopes
  • Monitor API key usage
  • Set up usage alerts
  • Revoke unused keys immediately

Code Examples

// ✅ Good: Environment variables
const client = new DripClient(
  process.env.DRIP_API_KEY,
  process.env.DRIP_REALM_ID
);

// ❌ Bad: Hardcoded keys
const client = new DripClient(
  'drip_1234567890abcdef',
  '507f1f77bcf86cd799439011'
);

// ✅ Good: Key rotation support
class SecureDripClient extends DripClient {
  async rotateKey(newApiKey) {
    // Test new key first
    const testClient = new DripClient(newApiKey, this.realmId);
    await testClient.request('GET', `/realms/${this.realmId}`);
    
    // If successful, update
    this.apiKey = newApiKey;
    console.log('API key rotated successfully');
  }
}

Monitoring and Analytics

Usage Tracking

class MonitoredDripClient extends DripClient {
  constructor(apiKey, realmId) {
    super(apiKey, realmId);
    this.stats = {
      requests: 0,
      errors: 0,
      lastUsed: null
    };
  }

  async request(method, endpoint, data) {
    this.stats.requests++;
    this.stats.lastUsed = new Date();
    
    try {
      const result = await super.request(method, endpoint, data);
      return result;
    } catch (error) {
      this.stats.errors++;
      throw error;
    }
  }

  getStats() {
    return {
      ...this.stats,
      errorRate: this.stats.errors / this.stats.requests,
      isActive: Date.now() - this.stats.lastUsed < 300000 // 5 minutes
    };
  }
}

Migration Strategies

From Realm to App Client

If you started with a realm client and want to expand to multiple realms:
1

Create App

Submit your app through the DRIP Apps portal
2

Parallel Development

Develop app client integration alongside existing realm client
3

Testing

Test app client with your own realm first
4

Gradual Migration

Migrate features one by one from realm client to app client
5

Deprecation

Once fully migrated, deprecate the realm client

Code Migration Example

// Before: Realm client
class RealmIntegration {
  constructor(apiKey, realmId) {
    this.client = new DripClient(apiKey, realmId);
  }

  async getLeaderboard() {
    return this.client.getLeaderboard();
  }
}

// After: App client supporting multiple realms
class AppIntegration {
  constructor(appClientSecret) {
    this.client = new DripAppClient(appClientSecret);
    this.authorizedRealms = new Map();
  }

  async getLeaderboard(realmId) {
    if (!this.authorizedRealms.has(realmId)) {
      throw new Error('Not authorized for this realm');
    }
    return this.client.getLeaderboard(realmId);
  }

  async loadAuthorizedRealms() {
    const realms = await this.client.getAuthorizedRealms();
    realms.forEach(realm => {
      this.authorizedRealms.set(realm.realmId, realm);
    });
  }
}

Next Steps