Skip to main content

Getting Started Guide

Key Features

Easy to set up

Our white-glove onboarding process ensures a smooth integration with your existing systems. Our expert team guides you through every step, from initial consultation to campaign launch. We handle the complex backend configurations, allowing you to focus on what matters most – creating engaging experiences for your users. With our personalized support, you'll be up and running quickly, leveraging the power of private-L1-blockchain-based rewards without the technical hassle.

Focus on your campaign

With Feature Platform, you can concentrate on crafting compelling campaigns that resonate with your audience. Our team works closely with you to design and implement custom reward strategies tailored to your specific goals. We manage the intricate details of activity tracking, rule enforcement, and reward distribution, freeing you to focus on creative campaign concepts and user engagement strategies. Let us handle the technical complexities while you drive the vision for your user interactions. Welcome to the Feature Platform! This guide will walk you through the initial steps to set up your account and begin creating engaging, reward-based experiences for your users. We offer a personalized "white glove" experience to ensure a smooth onboarding process.


In general integrating with the Feature Platform is a 6-step process:

  1. Account set up
  2. Integration workshop with your platform support representative
  3. API integration
  4. Webhook integration
  5. Testing the integration
  6. Go live

Step 1: Set Up Your Tenant Account

  1. Contact our sales team at sales@feature.io to discuss your needs and set up a tenant account.
  2. Once approved, you'll receive an email with instructions and credentials to start the integration process.

Step 2: Personalized Integration Workshop

  1. Our team will schedule a series of integration workshops with you to:
    • Understand your specific requirements
    • Design custom campaigns tailored to your needs
    • Configure activities, rules, and rewards
  2. During these workshops, we will:
    • Create and configure your Campaigns
    • Define Activities within each Campaign
    • Set up Rules and Conditions for Activities
    • Configure Digital Asset issuance as rewards
  3. After the workshops, we will provide you with:
    • campaign_ids and activity_ids for your reference
    • Detailed documentation of your configured campaigns and activities

Step 3: API Integration

  1. Integrating with the Feature Platform API to send User Activities requires sending a POST request to the activity endpoint.
    • The endpoint requires authenticating the request with a Hash-based Message Authentication Code (HMAC) signed with the Client Secret.
    • The request's payload accepts a JSON object with a single property activities containing an array of User Activities. This allows the Tenant System to send batches of User Activities.
      {
      "activities": [
      // One or more User Activity Objects
      // (more details about their schema below)
      ]
      }
    • Each User Activity object schema has two required properties:
      • activity_id provided at the end of the Integration Workshop on Step 2.
      • user_id an arbitrary unique identifier for the user in the context of the Tenant System. It will be used by the Feature Platform to assign any potential issued token ownership to that specific user.
      • Additionally, extra properties can be added to each User Activity object, if they're necessary to validate the Activity.
        {
        "user_id": "...", // arbitrary unique identifier to assign ownership of any token potentially issued as result of the activity
        "activity_id": "...", // each Campaign Activity defined during Step 2 will have a unique id
        // other properties necessary to validate the activity
        }
    • The final form of the User Activity POST request's payload will look something like:
      {
      "activities": [
      {
      "user_id": "...",
      "activity_id": "...",
      // ... other properties
      },
      // more user activity objects are allowed here
      ]
      }
  2. Implement the security token generation in your backend:
    • Authentication details have moved to a dedicated guide. Follow it to generate the Security Token and build the Authorization header required by all API calls.
    • See: Authentication
  3. Implement the API call to send user activities:
    1. The endpoint for the request is the /api/v1/activity (the base URL will be shared during Step 1)
    2. The verb to be used is POST
    3. The Authorization header is a Bearer Token composed by the concatenation of the API Key ID, the Signature and the Timestamp, all separated by spaces:
      • ${API_KEY_ID} ${SIGNATURE} ${TIMESTAMP}
    4. The request payload is a JSON object with an array of user activity objects, allowing for batch submission.
    5. In code, it would look something like this:
          async function sendUserActivity(config, userId, activityId) {
      // Build auth header as described in the Authentication guide
      const authHeader = config.authHeader; // e.g. "Bearer <API_KEY_ID> <SIGNATURE_HEX> <TIMESTAMP_MS>"
      const url = `${config.clientsApiBaseUrl}/api/v1/activity`;
      const headers = {
      'Authorization': authHeader,
      'Content-Type': 'application/json'
      };
      const body = JSON.stringify({
      "activities": [
      {
      user_id: userId,
      activity_id: activityId,
      }
      ]
      });

      const response = await fetch(url, {
      method: 'POST',
      headers: headers,
      body: body
      });

      return response.json();
      }
    6. Regarding the response's status code:
      • 207 Multi-Status: If the request was well constructed, accounting for different statuses for different user activities included in the request payload activities.
      • 400 Bad Request: If the request hasn't been correctly built.
      • 401 Unauthorized: If the Authorization Security Token was incorrectly built.
    7. The Feature Platform will process the user activities asynchronously, so it is not possible to know if any of them resulted in a token issuance based on the response.
      The platform will send any resulting token issuance to a designated Webhook Endpoint in the Tenant's System.

Step 4: Set Up the Webhook Endpoint

Create an endpoint in your system to receive webhook notifications from the Feature Platform. Our team will help you configure the webhook settings, including:

  • Setting up your webhook URL
  • Selecting the events you want to receive notifications for

Authentication Mechanism

The webhook authentication uses an HMAC (Hash-based Message Authentication Code) approach. This method provides a secure way to verify the integrity and the origin of the webhook payload.

The process is analogous with the generation of the Security Token used to send the User Activities.

Process Flow

  1. The Feature Platform will generate the webhook request payload.

    {
    "event": "external_process_succeeded",
    "activityId": "123456", // the same activity id sent in the respective user activity submission request
    "userId": "789012", // the same user id sent in the respective user activity submission request
    "completedAt": "2024-07-04T12:34:56Z" // timestamp when the token issuance happened
    //... etc
    }
  2. The Feature Platform will sign the request with the same API Key Secret used by the Tenant System to send the User Activity request.

  3. The signature and a timestamp are present in the webhook request custom headers.

  • x-feature-signature
  • x-feature-timestamp
  1. The Tenant System endpoint that receives the webhook can verify the signature using their API secret.

Signature Verification

The following code implements the webhook signature verification to ensure that incoming webhook requests are genuinely originating from the Feature Platform and haven't been tampered with. This code provides a robust mechanism for verifying the integrity and authenticity of webhook requests. By using HMAC, timestamping, and timing-safe comparison, it effectively mitigates common security risks.

import * as crypto from 'crypto';

function verifyWebhookSignature(payload: string, signature: string, timestamp: string, apiSecret: string): boolean {
const dataToSign = payload + timestamp;
const expectedSignature = crypto.createHmac('sha256', apiSecret).update(dataToSign).digest('hex');
return crypto.timingSafeEqual(Buffer.from(expectedSignature), Buffer.from(signature));
}

// Usage in Tenant's webhook handler
app.post('/webhook', (req, res) => {
const payload = JSON.stringify(req.body);
const signature = req.headers['x-feature-signature'] as string;
const timestamp = req.headers['x-feature-timestamp'] as string;

if (verifyWebhookSignature(payload, signature, timestamp, tenantApiSecret)) {
// Signature is valid, process the webhook
// ...
res.sendStatus(200);
} else {
// Invalid signature
res.sendStatus(401);
}
});

verifyWebhookSignature Function:

  1. **import * as crypto from 'crypto'; **: This line imports the built-in crypto module, which provides cryptographic functionality.
  2. function verifyWebhookSignature(...): This defines the function that performs the signature verification. It takes four arguments:
  • payload: The request body (as a string). This is the actual data being sent via the webhook.
  • signature: The signature received in the x-feature-signature header. This is the Feature Platform's cryptographic hash of the payload and timestamp, signed with the secret key.
  • timestamp: The timestamp received in the x-feature-timestamp header. This prevents replay attacks (where an attacker re-sends an old, valid request).
  • apiSecret: The shared secret key between the Tenant System and the Feature Platform. This secret MUST be kept confidential and should never be exposed in client-side code or committed to version control in plain text.
  1. **const dataToSign = payload + timestamp; **: This concatenates the payload and timestamp. This combined string will be used to generate the expected signature. The order is crucial; switching it would result in a different signature.
  2. **const expectedSignature = crypto.createHmac('sha256', apiSecret).update(dataToSign).digest('hex'); **: This is the core of the signature generation:
  • crypto.createHmac('sha256', apiSecret): Creates an HMAC (Hash-based Message Authentication Code) object using the SHA256 hashing algorithm and the apiSecret. HMAC is designed for message authentication.
  • .update(dataToSign): Updates the HMAC with the data to be signed (the combined payload and timestamp).
  • .digest('hex'): Calculates the final hash and encodes it as a hexadecimal string. This is the expectedSignature.
  1. **return crypto.timingSafeEqual(Buffer.from(expectedSignature), Buffer.from(signature)); **: This compares the expectedSignature (calculated by your server) with the signature received in the header.
    • Critically, it uses timingSafeEqual which ensures the comparison takes a constant amount of time, regardless of whether the strings match or not.
    • This prevents timing attacks where an attacker could infer information about the secret by measuring how long the comparison takes.

Webhook Handler Usage:

  1. app.post('/webhook', ...): Sets up a route to handle POST requests to the /webhook endpoint.
  2. **const payload = JSON.stringify(req.body); **: Extracts the request body and converts it to a JSON string. This ensures that the payload used for signature generation is consistent, even if the original req.body is an object.
  3. **const signature = req.headers['x-feature-signature'] as string; **: Retrieves the signature from the x-feature-signature header. The as string is a type assertion.
  4. **const timestamp = req.headers['x-feature-timestamp'] as string; **: Retrieves the timestamp from the x-feature-timestamp header.
  5. if (verifyWebhookSignature(...)): Calls the verifyWebhookSignature function to check if the signature is valid.
  6. res.sendStatus(200); or res.sendStatus(401);: Sends a 200 OK status if the signature is valid, or a 401 Unauthorized status if it's invalid.

Security Considerations

  1. Timestamp Validation: Tenants should validate the timestamp to prevent replay attacks. Reject webhooks with timestamps exceeding a specific threshold (e.g., 5 minutes).
  2. HTTPS: To ensure transport-level security, all webhook communications must be done over HTTPS.
  3. API Secret Management: Tenants must securely store their API secret and never expose it in client-side code or public repositories.
  4. Constant-Time Comparison: Use crypto.timingSafeEqual() to compare signatures and prevent timing attacks.
  5. API Key ID Storage: Ensure that the UserActivity records securely store the API Key ID used for their creation and that this ID is used to retrieve the correct API Secret for signature generation. This is paramount. Leakage of this secret compromises the entire verification process.

Best Practices for Tenants

  1. Implement Signature Verification: Always verify the signature of incoming webhooks before processing them.
  2. Use HTTPS: Ensure your webhook endpoint is configured to use HTTPS.
  3. Implement Idempotency: Design your webhook handler to be idempotent, as webhooks may be sent multiple times in rare cases.
  4. Log Failed Verifications: Keep logs of failed signature verifications for security auditing.
  5. Use Whitelisting: If possible, whitelist the IP addresses of the Feature Platform's webhook senders.
  6. API Key Rotation: Regularly rotate your API keys. When you do, ensure that you have a mechanism to handle webhooks that might still be using the old API secret for a short period after rotation.

Troubleshooting

Common issues and their solutions:

  1. Invalid Signature: Ensure you're using the correct API secret and that the payload hasn't been modified.
  2. Timestamp Mismatch: Check that your server's clock is synchronized correctly.
  3. Missing Headers: Verify that all required headers (X-Feature-Signature, X-Feature-Timestamp) are present in the request.
  4. Incorrect API Secret: If you've recently rotated your API keys, ensure that your webhook handler is using the correct, up-to-date API secret for verification.

Step 5: Testing and Integration Support

Our team will provide you access to the sandbox environment (sandbox.thefeature.io). We will guide you through the testing process:

  • Sending test activities using your implemented API calls
  • Verifying that your webhook endpoint receives notifications correctly
  • Ensuring activities and rewards are being recorded correctly

Our support team will be available to assist with any integration challenges you encounter.

Step 6: Go Live

Once testing is complete, our team will help you switch your API calls to the production environment (api.feature.io). We will update your webhook configuration for the production environment. Our team will closely monitor your first live campaigns and activities, providing support as needed.

Next Steps

We will schedule regular check-ins to review your campaigns' performance and discuss any necessary adjustments.

Explore our documentation for best practices in campaign creation and management.

For any questions or support needs during your integration process, please contact our dedicated support team at platform-support@feature.io.