Users API¶
The Users API provides access to user profile information and account details for authenticated users.
Overview¶
The /me endpoint retrieves the current authenticated user's profile information along with a paginated list of all brands the user has access to. This endpoint is essential for user context management, brand selection, and access control in your application.
Get User Profile¶
GET /me
Retrieve the current authenticated user's profile plus a paginated list of accessible brands.
Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
limit |
integer | No | Number of brands to return per page (default: 20, range: 1–100) |
cursor |
string | No | Cursor for pagination. Use the next_cursor value from the previous response to get the next page. |
Example Requests¶
Get user profile (default):
Get user profile with custom limit:
Get next page of brands:
curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
"https://partner-api.sherp.ai/me?limit=20&cursor=eyJicmFuZF9pZCI6MTIzfQ"
Response Format¶
{
"name": "John Doe",
"brands": [
{
"brand_id": 101,
"brand_name": "Acme Corporation",
"fb_accounts": [
{
"account_id": 1,
"account_name": "Acme FB Page"
}
],
"ig_accounts": [
{
"account_id": 2,
"account_name": "Acme Instagram"
}
]
},
{
"brand_id": 202,
"brand_name": "Globex Industries"
}
],
"next_cursor": "eyJicmFuZF9pZCI6MjAyfQ"
}
Response Fields¶
| 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 (optional) |
brands[].ig_accounts |
object[] | Instagram accounts mapped to the brand (optional) |
next_cursor |
string | Cursor to request the next page (null if no more brands) |
Pagination¶
The endpoint uses cursor-based pagination for brands. When a user has access to more than limit brands, the response includes a next_cursor field. Use this cursor value in the cursor query parameter to fetch the next page.
How it works:
1. Make your first request without a cursor parameter
2. If the response includes a next_cursor field, use that value in your next request
3. Continue until next_cursor is null or not present
Error Responses¶
401 Unauthorized:
401 Unauthorized (Missing Token):
500 Internal Server Error:
{
"detail": "Database error: Connection failed",
"error_code": "INTERNAL_SERVER_ERROR",
"status_code": 500,
"status": "error"
}
Best Practices¶
- Cache user data - Store user profile and brand list in your application to reduce API calls
- Use pagination - For users with many brands, implement pagination to improve performance
- Validate brand access - Always check if a user has access to a brand before making brand-specific API calls
- Handle authentication errors - Implement proper error handling for expired or invalid tokens
- Store brand context - Maintain the selected brand in your application state for better UX
Usage Examples¶
cURL¶
Get user profile:
Get user profile with pagination:
# First page
curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
"https://partner-api.sherp.ai/me?limit=20"
# Next page (use cursor from previous response)
curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
"https://partner-api.sherp.ai/me?limit=20&cursor=eyJicmFuZF9pZCI6MTIzfQ"
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
Related Documentation¶
- Authentication API - Get access tokens
- Analytics API - Access analytics data for brands
- Posts API - Access posts data for brands
- Error Handling - Handle API errors gracefully
- Authentication Guide - Complete auth setup
Need Help?¶
- Support - Contact our team