Skip to content

Rex Nutribot API Integration Guide

This guide walks you through integrating your application with the Rex Nutribot API. Follow these steps to get started quickly and efficiently.

Prerequisites

  • Python 3.7+ (for running tests and examples)
  • API key from the Rex Nutribot team

Quick Start

1. Get Your API Key

Contact the Rex Nutribot team to obtain your API key. You'll receive:

  • Development API key for testing
  • Production API key for live usage
  • Custom domain configuration (if applicable)

2. Set Up Authentication

All API requests require Bearer token authentication:

# Set as environment variable (recommended)
export REX_API_KEY="your_api_key_here"
# Or include in your code (less secure)
headers = {
    "Authorization": "Bearer REX_API_KEY",
    "Content-Type": "application/json"
}

3. Choose Your Environment

Development Environment:

  • Base URL: https://api.rex.fit/[org-id]/dev/v1
  • Use for testing and development
  • Safe to experiment with test data

Production Environment:

  • Base URL: https://api.rex.fit/[org-id]/prod/v1
  • Use for live applications
  • Real user data and billing

Testing Your Integration

1. Set Up Test Environment

# Install dependencies
pip install requests

# Set up test configuration
export REX_API_KEY="your_dev_api_key"
export REX_TEST_USER_ID="user_456"  # Use a valid test user ID

2. Message Webhook Test Example

import json
import unittest
from datetime import datetime
from typing import Any, Dict

import requests

class WebhookTest(unittest.TestCase):
    def setUp(self):
        self.base_url = "https://api.rex.fit/[org]/dev/v1"
        self.webhook_endpoint = f"{self.base_url}/message-webhook"
        self.api_key = ""

    def send_webhook(self, payload: Dict[str, Any]) -> requests.Response:
        """Helper method to send webhook requests"""
        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {self.api_key}",
        }
        try:
            response = requests.post(
                self.webhook_endpoint, json=payload, headers=headers
            )
            print(f"Response status: {response.status_code}")
            print(f"Response body: {response.text}")
            return response
        except requests.RequestException as e:
            self.fail(f"Request failed: {str(e)}")

    def generate_message_id(self) -> str:
        """Generate a unique message ID using timestamp"""
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S_%f")
        return f"msg_test_{timestamp}"

    def test_webhook_accepts_valid_message(self):
        """Test that webhook accepts a valid message payload"""
        payload = {
            "from_id": "user_456",
            "message_sid": self.generate_message_id(),
            "timestamp": "1672531200",
            "message_body": "Hello, this is a test message",
            "image_urls": [],
            "audio_urls": [],
        }

        response = self.send_webhook(payload)
        self.assertEqual(response.status_code, 200)

    def test_webhook_accepts_message_with_image(self):
        """Test that webhook accepts a message with an image"""
        payload = {
            "from_id": "user_456",
            "message_sid": self.generate_message_id(),
            "timestamp": "1672531200",
            "message_body": "i only ate half of my meal",
            "image_urls": [""], #send your own public link/signed url
            "audio_urls": [],
        }

        response = self.send_webhook(payload)
        self.assertEqual(response.status_code, 200)

    def test_webhook_rejects_missing_required_fields(self):
        """Test that webhook rejects payloads with missing required fields"""
        payload = {
            "message_sid": self.generate_message_id(),
            # Missing from_id
            "timestamp": "1672531200",
            "message_body": "Test message",
        }

        response = self.send_webhook(payload)
        self.assertEqual(response.status_code, 400)

    def test_webhook_rejects_invalid_method(self):
        """Test that webhook rejects non-POST methods"""
        response = requests.get(self.webhook_endpoint)
        self.assertEqual(response.status_code, 405)

    def test_webhook_rejects_invalid_user(self):
        """Test that webhook rejects messages from users not in the database"""
        payload = {
            "from_id": "nonexistent_user_123",  # User ID that doesn't exist in the database
            "message_sid": self.generate_message_id(),
            "timestamp": "1672531200",
            "message_body": "This user shouldn't be able to send messages",
            "image_urls": [],
            "audio_urls": [],
        }

        response = self.send_webhook(payload)
        self.assertEqual(
            response.status_code, 404
        )
        response_data = response.json()
        self.assertIn("error", response_data)
        self.assertIn("user not found", response_data["error"].lower())

if __name__ == "__main__":
    unittest.main(verbosity=2)

3. User Creation Test Example

# Test cases for create_user API endpoint
import requests

def test_create_user():
    """Test cases for user creation API"""

    # Test Case 1: Valid user with metric measurements
    valid_metric_user = {
        "from_id": "user_789",
        "first_name": "John",
        "last_name": "Doe",
        "birthdate": "1990-01-01",
        "gender": "male",
        "language": "en",
        "goal": "lose weight",
        "timezone": "Kuwait, Kuwait (UTC+03:00)",
        "height_cm": 180,
        "weight_kg": 80,
        "display_name": "JohnD",
    }

    # Test Case 2: Valid user with imperial measurements
    valid_imperial_user = {
        "from_id": "user_101",
        "first_name": "Jane",
        "last_name": "Smith",
        "birthdate": "1995-06-15",
        "gender": "female",
        "language": "en",
        "goal": "lose weight",
        "timezone": "New York, USA (UTC-05:00)",
        "height_ft": "5'7",
        "weight_lbs": 150,
    }

    # Test Case 3: Invalid - Missing required field
    missing_required_field = {
        "from_id": "user_789",
        "first_name": "Bob",
        # missing last_name
        "birthdate": "1985-12-31",
        "gender": "male",
        "language": "en",
        "goal": "gain muscle",
        "timezone": "Sydney, Australia (UTC+10:00)",
        "height_cm": 175,
        "weight_kg": 70,
    }

    # Test Case 4: Invalid - Both measurement systems provided
    both_measurement_systems = {
        "from_id": "user_101",
        "first_name": "Alice",
        "last_name": "Johnson",
        "birthdate": "1988-03-20",
        "gender": "female",
        "language": "de",
        "goal": "maintain",
        "timezone": "Berlin, Germany (UTC+01:00)",
        "height_cm": 165,
        "weight_kg": 60,
        "height_ft": "5'5",
        "weight_lbs": 132,
    }

    # Test Case 5: Invalid - Invalid language code
    invalid_language = {
        "from_id": "user_102",
        "first_name": "Maria",
        "last_name": "Garcia",
        "birthdate": "1992-09-10",
        "gender": "female",
        "language": "fr",  # Invalid language code
        "goal": "lose weight",
        "timezone": "Madrid, Spain (UTC+01:00)",
        "height_cm": 170,
        "weight_kg": 65,
    }

    # Test Case 6: Invalid - Invalid goal
    invalid_goal = {
        "from_id": "user_103",
        "first_name": "Mike",
        "last_name": "Wilson",
        "birthdate": "1987-11-25",
        "gender": "male",
        "language": "en",
        "goal": "get stronger",  # Invalid goal
        "timezone": "Toronto, Canada (UTC-05:00)",
        "height_cm": 185,
        "weight_kg": 90,
    }

    # Test Case 7: Invalid - Invalid timezone format
    invalid_timezone = {
        "from_id": "user_104",
        "first_name": "Sarah",
        "last_name": "Brown",
        "birthdate": "1993-07-08",
        "gender": "female",
        "language": "en",
        "goal": "maintain",
        "timezone": "London GMT+0",  # Invalid timezone format
        "height_cm": 168,
        "weight_kg": 58,
    }

    # Test Case 8: Invalid - Invalid date format
    invalid_date = {
        "from_id": "user_105",
        "first_name": "David",
        "last_name": "Lee",
        "birthdate": "01-01-1990",  # Invalid date format
        "gender": "male",
        "language": "en",
        "goal": "gain muscle",
        "timezone": "Singapore (UTC+08:00)",
        "height_cm": 175,
        "weight_kg": 75,
    }

    # Test Case 9: Invalid - Invalid height_ft format
    invalid_height_ft = {
        "from_id": "user_106",
        "first_name": "Tom",
        "last_name": "Clark",
        "birthdate": "1991-04-15",
        "gender": "male",
        "language": "en",
        "goal": "maintain",
        "timezone": "Chicago, USA (UTC-06:00)",
        "height_ft": "5.10",  # Invalid format (should be 5'10)
        "weight_lbs": 160,
    }

    # Test Case 10: Invalid - No measurement system provided
    no_measurements = {
        "from_id": "user_107",
        "first_name": "Emma",
        "last_name": "Davis",
        "birthdate": "1994-08-30",
        "gender": "female",
        "language": "en",
        "goal": "lose weight",
        "timezone": "Dublin, Ireland (UTC+00:00)",
        # No height/weight measurements provided
    }

    test_cases = [
        (valid_metric_user, 201, "Valid metric user creation"),
        (valid_imperial_user, 201, "Valid imperial user creation"),
        (missing_required_field, 400, "Missing required field"),
        (both_measurement_systems, 400, "Both measurement systems provided"),
        (invalid_language, 400, "Invalid language code"),
        (invalid_goal, 400, "Invalid goal"),
        (invalid_timezone, 400, "Invalid timezone format"),
        (invalid_date, 400, "Invalid date format"),
        (invalid_height_ft, 400, "Invalid height_ft format"),
        (no_measurements, 400, "No measurement system provided"),
    ]

    return test_cases

def run_tests(base_url, api_key):
    """Run all test cases against the API endpoint"""

    headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}

    test_cases = test_create_user()

    for payload, expected_status, description in test_cases:
        try:
            response = requests.post(f"{base_url}", json=payload, headers=headers)

            actual_status = response.status_code
            result = "PASS" if actual_status == expected_status else "FAIL"

            print(f"{result}: {description}")
            print(f"Expected status: {expected_status}, Got: {actual_status}")
            if result == "FAIL":
                print(f"Response: {response.json()}")
            print("---")

        except Exception as e:
            print(f"Error testing {description}: {str(e)}")
            print("---")

if __name__ == "__main__":
    run_tests(
        "https://api.rex.fit/[org]/dev/v1/create-user",
        "", #API key here
    )

4. Dashboard Test Example

import unittest
from typing import Any, Dict

import requests

class DashboardLinkTest(unittest.TestCase):
    def setUp(self):
        # Configure your test environment
        self.endpoint = "https://api.rex.fit/[org]/dev/v1/dashboard-url"
        self.api_key = ""  # Your API key

    def get_dashboard_link(
        self, user_id: str = None, api_key: str = None
    ) -> requests.Response:
        """Helper method to make requests to the dashboard link endpoint"""
        headers = {}
        if api_key:
            headers["Authorization"] = f"Bearer {api_key}"

        params = {}
        if user_id:
            params["user_id"] = user_id

        try:
            response = requests.get(self.endpoint, headers=headers, params=params)
            print(f"Response status: {response.status_code}")
            print(f"Response body: {response.text}")
            return response
        except requests.RequestException as e:
            self.fail(f"Request failed: {str(e)}")

    def test_valid_request(self):
        """Test getting dashboard link for valid user"""
        # Use a known valid user ID from your database
        response = self.get_dashboard_link(user_id="user_456", api_key=self.api_key)

        self.assertEqual(response.status_code, 200)
        data = response.json()
        self.assertEqual(data["status"], "success")
        self.assertIn("dashboard_url", data)
        self.assertTrue(data["dashboard_url"].startswith("https://"))

    def test_missing_api_key(self):
        """Test request without API key"""
        response = self.get_dashboard_link(user_id="user_456", api_key=None)

        self.assertEqual(response.status_code, 401)
        data = response.json()
        self.assertEqual(data["status"], "error")
        self.assertIn("Authorization header", data["message"])

    def test_invalid_api_key(self):
        """Test request with invalid API key"""
        response = self.get_dashboard_link(user_id="user_456", api_key="invalid_key")

        self.assertEqual(response.status_code, 401)
        data = response.json()
        self.assertEqual(data["status"], "error")
        self.assertEqual(data["message"], "Invalid API key")

    def test_missing_user_id(self):
        """Test request without user_id parameter"""
        response = self.get_dashboard_link(user_id=None, api_key=self.api_key)

        self.assertEqual(response.status_code, 400)
        data = response.json()
        self.assertEqual(data["status"], "error")
        self.assertEqual(data["message"], "Missing 'user_id'")

    def test_nonexistent_user(self):
        """Test request with user ID that doesn't exist"""
        response = self.get_dashboard_link(
            user_id="nonexistent_user_999", api_key=self.api_key
        )

        self.assertEqual(response.status_code, 404)
        data = response.json()
        self.assertEqual(data["status"], "error")
        self.assertEqual(data["message"], "User not found")

    def test_malformed_api_key(self):
        """Test request with malformed Authorization header"""
        headers = {"Authorization": "InvalidFormat xyz123"}
        params = {"user_id": "user_456"}

        response = requests.get(self.endpoint, headers=headers, params=params)

        self.assertEqual(response.status_code, 401)
        data = response.json()
        self.assertEqual(data["status"], "error")
        self.assertIn("Bearer", data["message"])

if __name__ == "__main__":
    unittest.main(verbosity=2)

Support and Resources

  • Rex Nutribot Support: Contact Rex Nutribot team for technical support
  • API Updates: Monitor repository for API changes and updates

Ready to integrate? Start with the test examples above to validate your setup!