Skip to content

Users API

The Users API provides access to user profile information and account details for authenticated users.

GET /me

Retrieve the current authenticated user's profile plus a paginated list of accessible brands.

Request

Endpoint: GET /me Authentication: Required (Bearer token)

Headers

Authorization: Bearer YOUR_ACCESS_TOKEN

Query Parameters

Parameter Type Default Description
limit integer 20 Number of brands to return per page (1–100)
cursor string null Use the next_cursor from the previous response to fetch the next page

Response

Success (200 OK)

Returns the user's profile information:

{
  "name": "John Doe",
  "brands": [
    {
      "brand_id": 101,
      "brand_name": "Acme Corporation"
    },
    {
      "brand_id": 202,
      "brand_name": "Globex Industries"
    }
  ],
  "next_cursor": null
}
Field Type Description
name string User's display name
brands object[] Page of brands the user has access to
brands[].brand_id integer Unique brand identifier
brands[].brand_name string Brand display name
brands[].fb_accounts object[] Facebook accounts mapped to the brand
brands[].ig_accounts object[] Instagram accounts mapped to the brand
next_cursor string Cursor to request the next page (null if no more brands)

Error Responses

401 Unauthorized - Invalid Token
{
  "detail": "Could not validate credentials"
}
401 Unauthorized - Missing Token
{
  "detail": "Not authenticated"
}
500 Internal Server Error
{
  "detail": "Database error: Connection failed"
}

Usage Examples

cURL

# Get current user profile
curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  https://partner-api.sherp.ai/me

JavaScript/Node.js

async function getCurrentUser(accessToken) {
  try {
    const response = await fetch('https://partner-api.sherp.ai/me', {
      headers: {
        'Authorization': `Bearer ${accessToken}`
      }
    });

    if (!response.ok) {
      const error = await response.json();
      throw new Error(`HTTP ${response.status}: ${error.detail}`);
    }

    const user = await response.json();

    if (user === null) {
      console.log('User not found in system database');
      return null;
    }

    console.log('Current user:', user);
    console.log(`User has access to ${user.brands.length} brand(s)`);

    return user;
  } catch (error) {
    console.error('Failed to get user profile:', error.message);
    throw error;
  }
}

// Usage
const accessToken = localStorage.getItem('access_token');
getCurrentUser(accessToken)
  .then(user => {
    if (user) {
      document.getElementById('userName').textContent = user.name;
      displayUserBrands(user.brands);
    }
  })
  .catch(error => {
    console.error('Error:', error.message);
    // Redirect to login if unauthorized
    if (error.message.includes('401')) {
      window.location.href = '/login';
    }
  });

Python

import requests
from typing import Optional, Dict, Any

def get_current_user(access_token: str) -> Optional[Dict[str, Any]]:
    """Get the current user's profile information."""
    url = "https://partner-api.sherp.ai/me"
    headers = {
        "Authorization": f"Bearer {access_token}"
    }

    try:
        response = requests.get(url, headers=headers, timeout=10)
        response.raise_for_status()

        user_data = response.json()

        if user_data is None:
            print("User not found in system database")
            return None

        brand_list = user_data.get("brands") or []
        print(f"Current user: {user_data.get('name', 'Unknown User')}")
        print(f"Access to {len(brand_list)} brand(s)")

        return user_data

    except requests.exceptions.HTTPError as e:
        if response.status_code == 401:
            print("Authentication failed - token may be expired")
        else:
            print(f"HTTP error: {e}")
        raise
    except requests.exceptions.RequestException as e:
        print(f"Request error: {e}")
        raise

# Usage
try:
    access_token = "your_access_token_here"
    user = get_current_user(access_token)

    if user:
        # List available brands
        for brand in user.get("brands", []):
            print(f"Brand: {brand['brand_name']} (ID: {brand['brand_id']})")

except Exception as e:
    print(f"Failed to get user profile: {e}")

PHP

<?php

function getCurrentUser($accessToken) {
    $url = 'https://partner-api.sherp.ai/me';

    $options = [
        'http' => [
            'header' => "Authorization: Bearer $accessToken\r\n",
            'method' => 'GET'
        ]
    ];

    $context = stream_context_create($options);
    $result = file_get_contents($url, false, $context);

    if ($result === FALSE) {
        throw new Exception('Failed to get user profile');
    }

    $user = json_decode($result, true);

    if ($user === null) {
        echo "User not found in system database\n";
        return null;
    }

    return $user;
}

// Usage
try {
    $accessToken = 'your_access_token_here';
    $user = getCurrentUser($accessToken);

    if ($user) {
        echo "User: " . $user['name'] . "\n";
        echo "Brands: " . count($user['brands']) . "\n";

        foreach ($user['brands'] as $brand) {
            echo "- " . $brand['brand_name'] . " (ID: " . $brand['brand_id'] . ")\n";
        }
    }
} catch (Exception $e) {
    echo "Error: " . $e->getMessage() . "\n";
}
?>

Brand Access

The brands array contains all brands the user has access to. Use this to:

  • Filter data in your application
  • Populate brand selection dropdowns
  • Validate brand access for API calls
function getUserBrandIds(user) {
  return user.brands.map(brand => brand.brand_id);
}

function canAccessBrand(user, brandId) {
  return user.brands.some(brand => brand.brand_id === brandId);
}

// Usage
const brandIds = getUserBrandIds(user);
const canAccess = canAccessBrand(user, 101);

Integration Patterns

User Context Management

class UserContext {
  constructor() {
    this.user = null;
    this.accessToken = localStorage.getItem('access_token');
  }

  async loadUser() {
    if (!this.accessToken) {
      throw new Error('No access token available');
    }

    this.user = await getCurrentUser(this.accessToken);
    return this.user;
  }

  getBrandIds() {
    return this.user ? this.user.brands.map(b => b.brand_id) : [];
  }

  getDisplayName() {
    return this.user ? this.user.name : 'Unknown User';
  }
}

// Usage
const userContext = new UserContext();
await userContext.loadUser();

Error Handling

async def get_user_with_retry(access_token: str, max_retries: int = 3):
    """Get user profile with automatic retry on failure."""
    for attempt in range(max_retries):
        try:
            return get_current_user(access_token)
        except requests.exceptions.HTTPError as e:
            if e.response.status_code == 401:
                # Don't retry authentication errors
                raise
            if attempt == max_retries - 1:
                raise
            await asyncio.sleep(2 ** attempt)  # Exponential backoff

    return None

Common Use Cases

User Profile Display

function displayUserProfile(user) {
  document.getElementById('userName').textContent = user.name;

  const brandsList = document.getElementById('userBrands');
  brandsList.innerHTML = user.brands.map(brand =>
    `<option value="${brand.brand_id}">${brand.brand_name}</option>`
  ).join('');
}

Brand Selection

function createBrandSelector(user) {
  const selector = document.createElement('select');
  selector.id = 'brandSelector';

  user.brands.forEach(brand => {
    const option = document.createElement('option');
    option.value = brand.brand_id;
    option.textContent = brand.brand_name;
    selector.appendChild(option);
  });

  return selector;
}

Security Considerations

  • Token Validation: The endpoint validates the Firebase JWT token server-side
  • User Context: User data is fetched from the authenticated token, not parameters
  • Brand Access: Only brands the user has access to are returned
  • Role Enforcement: Implement client-side and server-side role checking

Need help with the Users API? Contact our support team.