MangoApps Ruby SDK
A clean, Ruby SDK for MangoApps APIs with OAuth2/OpenID Connect authentication.
Installation
Add this line to your application's Gemfile:
gem "mangoapps-ex-sdk-ruby"
And then execute:
bundle install
Or install it directly:
gem install mangoapps-ex-sdk-ruby
Basic Usage Example
require 'mangoapps-ex-sdk-ruby'
# Initialize client
client = MangoApps::Client.new
# Get user profile
user = client.me
puts "Hello, #{user.name}!"
# Get OAuth user info (from OAuth userinfo endpoint)
userinfo = client.get_userinfo
puts "OAuth User: #{userinfo.name} (#{userinfo.email})"
puts "Username: #{userinfo.preferred_username}"
puts "Subject ID: #{userinfo.sub}"
# Get priority items
priority_items = client.my_priority_items
puts "You have #{priority_items.data.length} priority items:"
priority_items.data.each do |item|
  puts "  • #{item.title}: #{item.count} pending"
end
# Get available courses
courses = client.course_catalog
puts "Available courses: #{courses.courses.length}"
# Get activity feeds
feeds = client.feeds(offset: 0, limit: 20, all_comments: 'Y')
puts "Activity feeds: #{feeds.feeds.length} (unread: #{feeds.unread_counts.unread_feeds_count})"
# Get all posts
posts = client.get_all_posts(filter_by: "all", offset: 0, limit: 20)
puts "All posts: #{posts.feeds.length}"
# Get post details by ID
if posts.feeds.any?
  post_id = posts.feeds.first.post_id
  post_details = client.get_post_by_id(post_id, full_description: "Y")
  puts "Post details: #{post_details.post.title}"
end
# Get user libraries
libraries = client.get_libraries(offset: 0, limit: 20)
puts "User libraries: #{libraries.libraries.length}"
# Get library categories by ID
if libraries.libraries.any?
  library_id = libraries.libraries.first.id
  library_details = client.get_library_categories(library_id, offset: 0, limit: 20)
  puts "Library details: #{library_details.library.name}"
  # Get library items from first category
  if library_details.library.categories.any?
    category_id = library_details.library.categories.first.id
    library_items = client.get_library_items(library_id, category_id, offset: 0, limit: 20)
    puts "Library items: #{library_items.library_items.length} items in #{library_items.category_name}"
  end
end
# Get user trackers
trackers = client.get_trackers(page: 1, limit: 20)
puts "User trackers: #{trackers.trackers.length}"
# Get user folders (no pagination)
folders = client.get_folders
puts "User folders: #{folders.folders.length}"
# Get files from first folder with content (no pagination)
if folders.folders.any?
  folder_with_content = folders.folders.find { |f| f.child_count.to_i > 0 }
  if folder_with_content
    folder_files = client.get_folder_files(folder_with_content.id, include_folders: "Y")
    puts "Folder files: #{folder_files.files.length} items in #{folder_files.name}"
  end
end
# Get user tasks
tasks = client.get_tasks(filter: "Pending_Tasks", page: 1, limit: 3)
puts "User tasks: #{tasks.tasks.task.length}"
# Get detailed information for a specific task
if tasks.tasks.task.any?
  first_task = tasks.tasks.task.first
  task_id = first_task.is_a?(Array) ? first_task[1] : first_task.id
  task_details = client.get_task_details(task_id)
  puts "Task details: #{task_details.task.task_title} (Status: #{task_details.task.status})"
end
# Get user wikis
wikis = client.get_wikis(mode: "my", offset: 0, limit: 5)
puts "User wikis: #{wikis.wikis.length}"
# Get detailed information for the first wiki
if wikis.wikis.any?
  first_wiki = wikis.wikis.first
  wiki_details = client.get_wiki_details(first_wiki.id)
  puts "Wiki details: #{wiki_details.wiki.details.title} (Read count: #{wiki_details.wiki.details.total_read_count})"
end
Pagination Support
Most list APIs support optional pagination parameters for efficient data retrieval:
# Basic usage with default pagination
posts = client.get_all_posts
courses = client.course_catalog
# Pagination with custom offset and limit (offset-based)
posts = client.get_all_posts(filter_by: "all", offset: 20, limit: 10)
courses = client.course_catalog(page: 1, limit: 5)
# Pagination with custom page and limit (page-based)
tasks = client.get_tasks(filter: "Pending_Tasks", page: 1, limit: 10)
trackers = client.get_trackers(page: 1, limit: 15)
# Library items with offset-based pagination
items = client.get_library_items(library_id, category_id, offset: 0, limit: 15)
Pagination Types:
- Offset-based APIs: 
get_all_posts,get_libraries,get_library_categories,get_library_items,notifications,get_wikis,feeds - Page-based APIs: 
course_catalog,get_tasks,get_trackers - Non-paginated APIs: 
course_categories,award_categories,get_awards_list,get_folders,get_folder_files 
Default Pagination Values:
- Offset-based: 
offset: 0, limit: 20 - Page-based: 
page: 1, limit: 20 - Tasks: 
page: 1, limit: 5(smaller default for task management) - Posts: 
offset: 0, limit: 20withfilter_by: "all" 
Available Modules
✅ Currently Implemented
Users Module
- User Profile: 
client.me- Get current user information with clean dot notation access 
Learn Module
- Course Catalog: 
client.course_catalog- Get available courses - Course Categories: 
client.course_categories- Get course categories - Course Details: 
client.course_details(course_id)- Get detailed course information by ID - My Learning: 
client.my_learning- Get user's learning progress and courses 
Recognitions Module
- Award Categories: 
client.award_categories- Get recognition award categories - Get Awards List: 
client.get_awards_list(category_id: id)- Get awards for a specific category - Get Profile Awards: 
client.get_profile_awards- Get user's personal awards and activity - Core Value Tags: 
client.core_value_tags- Get core value tags for recognition - Leaderboard Info: 
client.leaderboard_info- Get user and team leaderboard information 
Notifications Module
- My Priority Items: 
client.my_priority_items- Get user's priority items including requests, events, quizzes, surveys, tasks, and todos - Notifications: 
client.notifications- Get user's notifications with unread counts and detailed notification information 
Feeds Module
- Feeds: 
client.feeds- Get user's activity feeds with unread counts and feed details 
Posts Module
- Get All Posts: 
client.get_all_posts(filter_by: "all")- Get all posts with filtering options - Get Post By ID: 
client.get_post_by_id(post_id, full_description: "Y")- Get detailed post information by ID 
Libraries Module
- Get Libraries: 
client.get_libraries- Get user's document libraries with categories and items - Get Library Categories: 
client.get_library_categories(library_id)- Get detailed library information and categories by library ID - Get Library Items: 
client.get_library_items(library_id, category_id)- Get library items by library ID and category ID 
Trackers Module
- Get Trackers: 
client.get_trackers- Get user's trackers with submission dates and conversation details 
Attachments Module
- Get Folders: 
client.get_folders- Get user's file folders with permissions and metadata - Get Folder Files: 
client.get_folder_files(folder_id, include_folders: "Y")- Get files and folders inside a specific folder 
Tasks Module
- Get Tasks: 
client.get_tasks(filter: "Pending_Tasks", page: 1, limit: 5)- Get user's tasks with filtering, pagination, and detailed task information - Get Task Details: 
client.get_task_details(task_id)- Get detailed information for a specific task by ID 
Wikis Module
- Get Wikis: 
client.get_wikis(mode: "my", limit: 20, offset: 0)- Get user's wikis with filtering, pagination, and detailed wiki information - Get Wiki Details: 
client.get_wiki_details(wiki_id)- Get detailed information for a specific wiki by ID 
Complete Examples
Notifications Management
require 'mangoapps-ex-sdk-ruby'
# Initialize client
client = MangoApps::Client.new
# Get user's priority items
priority_items = client.my_priority_items
# Display all priority items with details
puts "🔔 User Priority Items Dashboard"
puts "================================"
puts "Success: #{priority_items.success}"
puts "Display Type: #{priority_items.display_type}"
puts ""
priority_items.data.each do |item|
  puts "📋 #{item.title} (ID: #{item.id})"
  puts "   Count: #{item.count} pending items"
  puts "   Action Type: #{item.action_type}"
  puts "   Icon: #{item.icon} (#{item.icon_color})"
  puts "   Background: #{item.icon_bg_color}"
  puts "   Description: #{item.info_details.gsub(/<[^>]*>/, '').strip[0..100]}..."
  puts ""
end
# Get user's notifications
notifications = client.notifications
# Display notifications dashboard
puts "🔔 User Notifications Dashboard"
puts "==============================="
puts "What's new: #{notifications.whats_new_count}"
puts "Unread feeds: #{notifications.unread_feeds_count}"
puts "Mentions: #{notifications.mention_count}"
puts "Direct messages: #{notifications.}"
puts "Unread notifications: #{notifications.unread_notification_count}"
puts ""
notifications.notifications.first(5).each do |notification|
  puts "📢 #{notification.sender_name} (ID: #{notification.id})"
  puts "   Text: #{notification.text[0..100]}..."
  puts "   Type: #{notification.notification_type || 'None'}"
  puts "   Read: #{notification.is_read} | Updated: #{Time.at(notification.updated_at.to_i).strftime('%Y-%m-%d %H:%M:%S')}"
  puts "   MLink: #{notification.mlink || 'None'}"
  if notification. && notification..any?
    puts "   Mentions: #{notification..map { |tag| tag.mention }.join(', ')}"
  end
  puts ""
end
# Filter by specific action types
approval_items = priority_items.data.select { |item| item.action_type == 'approval' }
puts "🔍 Approval Items: #{approval_items.length}"
approval_items.each do |item|
  puts "  • #{item.title}: #{item.count} items"
end
# Get high-priority items (count > 5)
high_priority = priority_items.data.select { |item| item.count > 5 }
puts "⚠️  High Priority Items: #{high_priority.length}"
high_priority.each do |item|
  puts "  • #{item.title}: #{item.count} items"
end
User Profile Management
# Get current user profile
user = client.me
# Access user information with clean dot notation
puts "Name: #{user.user_profile.minimal_profile.name}"
puts "Email: #{user.user_profile.minimal_profile.email}"
puts "User Type: #{user.user_profile.minimal_profile.user_type}"
# Access user statistics
puts "Followers: #{user.user_profile.user_data.followers}"
puts "Following: #{user.user_profile.user_data.following}"
# Access gamification data
puts "Current Level: #{user.user_profile.gamification.current_level}"
puts "Total Points: #{user.user_profile.gamification.total_points}"
puts "Badges: #{user.user_profile.gamification.badges.length}"
# Access recognition data
puts "Reward Points Received: #{user.user_profile.recognition.total_reward_points_received}"
Learning Management
# Get course catalog
courses = client.course_catalog
# Browse available courses
courses.courses.each do |course|
  puts "📚 #{course.name}"
  puts "   Type: #{course.course_type}"
  puts "   Delivery: #{course.delivery_mode}"
  puts "   URL: #{course.start_course_url}"
  puts ""
  # Get detailed course information
  course_details = client.course_details(course.id)
  detailed_course = course_details.course
  puts "   📖 Detailed Info:"
  puts "   Description: #{detailed_course.description}"
  puts "   Instructors: #{detailed_course.instructors.length}"
  puts "   Fields: #{detailed_course.fields.length}"
  puts ""
end
# Get course categories
categories = client.course_categories
# Browse course categories
categories.all_categories.each do |category|
  puts "📂 #{category.name}"
  puts "   Position: #{category.position}"
  puts "   Icon: #{category.icon_properties}"
  puts ""
end
# Get user's learning progress
learning = client.my_learning
# Display learning summary
puts "🎓 Learning Summary for #{learning.user_name}"
puts "⏱️ Total training time: #{learning.total_training_time}"
puts "📚 Ongoing: #{learning.ongoing_course_count} | ✅ Completed: #{learning.completed_course_count} | 📝 Registered: #{learning.registered_course_count}"
puts ""
# Browse learning sections
learning.section.each do |section|
  puts "📂 #{section.label} (#{section.count} courses)"
  section.courses.each do |course|
    puts "  📚 #{course.name}"
    puts "     Progress: #{course.course_progress}%"
    puts "     Type: #{course.course_type}"
    puts "     URL: #{course.start_course_url}"
    puts ""
  end
end
Recognition Management
# Get award categories
categories = client.award_categories
# Display available award categories
puts "🏆 Available Award Categories:"
categories.award_categories.each do |category|
  puts "  • #{category.name} (ID: #{category.id})"
  puts "    Permission: #{category.}"
end
puts ""
# Get awards for a specific category
category_id = 4303  # Safety & Quality category
awards = client.get_awards_list(category_id: category_id)
# Display awards in the category
puts "🏆 Awards in Category #{category_id}:"
awards.get_awards_list.each do |award|
  puts "  • #{award.name} (ID: #{award.id})"
  puts "    Points: #{award.points} | Reward Points: #{award.reward_points || 'None'}"
  puts "    Description: #{award.description}"
end
puts ""
# Get user profile awards
profile_awards = client.get_profile_awards
# Display user's personal awards
puts "🏆 User Profile Awards:"
puts "  Core Value Tags:"
profile_awards..each do |tag|
  puts "    • #{tag.name} (ID: #{tag.id}) - Count: #{tag.count}"
end
puts "  Recent Awards:"
profile_awards.feeds.each do |feed|
  puts "    • #{feed.feed_property.title} - Points: #{feed.recognition_points}"
  puts "      From: #{feed.from_user.name}"
end
puts ""
# Get user priority items
priority_items = client.my_priority_items
# Display priority items
puts "🔔 User Priority Items:"
priority_items.data.each do |item|
  puts "  • #{item.title} (ID: #{item.id}) - Count: #{item.count}"
  puts "    Action Type: #{item.action_type} | Icon: #{item.icon}"
end
puts ""
# Get user activity feeds
feeds = client.feeds
# Display feeds
puts "📰 User Activity Feeds:"
puts "  Total feeds: #{feeds.feeds.length}"
puts "  Unread feeds: #{feeds.unread_counts.unread_feeds_count}"
puts "  Direct messages: #{feeds.unread_counts.}"
puts "  What's new: #{feeds.unread_counts.whats_new_count}"
puts ""
# Display recent feeds
puts "📰 Recent Feeds:"
feeds.feeds.first(3).each do |feed|
  puts "  • #{feed.feed_property.title} (ID: #{feed.id})"
  puts "    From: #{feed.from_user.name} | Group: #{feed.group_name}"
  puts "    Type: #{feed.feed_type} | Unread: #{feed.unread}"
end
puts ""
# Get all posts
posts = client.get_all_posts(filter_by: "all")
# Display posts
puts "📝 All Posts:"
puts "  Total posts: #{posts.feeds.length}"
puts "  Post view count visibility: #{posts.post_view_count_visibility}"
puts ""
# Display recent posts
puts "📝 Recent Posts:"
posts.feeds.first(3).each do |post|
  puts "  • #{post.tile.tile_name} (ID: #{post.id})"
  puts "    From: #{post.from_user.name} | Group: #{post.group_name}"
  puts "    Views: #{post.total_view_count} | Comments: #{post.comments.length}"
end
puts ""
# Get detailed post information
if posts.feeds.any?
  first_post_id = posts.feeds.first.post_id
  post_details = client.get_post_by_id(first_post_id, full_description: "Y")
  puts "📝 Post Details (ID: #{first_post_id}):"
  puts "  Title: #{post_details.post.title}"
  puts "  Created by: #{post_details.post.created_name}"
  puts "  View count: #{post_details.post.total_view_count}"
  puts "  Can edit: #{post_details.post.can_edit} | Can comment: #{post_details.post.can_comment}"
  puts "  Full description available: #{post_details.post.tile.tile_full_description.length > 0 ? 'Yes' : 'No'}"
end
puts ""
# Get user libraries
libraries = client.get_libraries
puts "📚 User Libraries:"
puts "  Total libraries: #{libraries.libraries.length}"
puts ""
# Display recent libraries
puts "📚 Recent Libraries:"
libraries.libraries.first(3).each do |library|
  puts "  • #{library.name} (ID: #{library.id})"
  puts "    Type: #{library.library_type} | Items: #{library.total_items_count}"
  puts "    Categories: #{library.categories.length} | Edit access: #{library.edit_access}"
end
puts ""
# Get detailed library information
if libraries.libraries.any?
  first_library_id = libraries.libraries.first.id
  library_details = client.get_library_categories(first_library_id)
  puts "📚 Library Details (ID: #{first_library_id}):"
  puts "  Name: #{library_details.library.name}"
  puts "  Type: #{library_details.library.library_type} | View: #{library_details.library.view_mode}"
  puts "  Total items: #{library_details.library.total_items_count}"
  puts "  Categories: #{library_details.library.categories.length}"
  puts "  Edit access: #{library_details.library.edit_access}"
  # Get library items from first category
  if library_details.library.categories.any?
    first_category_id = library_details.library.categories.first.id
    library_items = client.get_library_items(first_library_id, first_category_id)
    puts "📚 Library Items (Category: #{library_items.category_name}):"
    puts "  View mode: #{library_items.view_mode} | Library type: #{library_items.library_type}"
    puts "  Items count: #{library_items.library_items.length}"
    puts "  Can add: #{library_items.can_add}"
  end
end
puts ""
# Get user trackers
trackers = client.get_trackers
puts "📊 User Trackers:"
puts "  Total trackers: #{trackers.trackers.length}"
puts ""
# Display recent trackers
puts "📊 Recent Trackers:"
trackers.trackers.first(3).each do |tracker|
  puts "  • #{tracker.name} (ID: #{tracker.id})"
  puts "    Last submission: #{Time.at(tracker.last_submission_date.to_i).strftime('%Y-%m-%d %H:%M:%S')}"
  puts "    Conversation: #{tracker.conversation_name}"
  puts "    Pinned: #{tracker.is_pinned} | Can share: #{tracker.can_share}"
end
puts ""
# Get user folders
folders = client.get_folders
puts "📁 User Folders:"
puts "  Total folders: #{folders.folders.length}"
puts ""
# Display first few folders
puts "📁 Available Folders:"
folders.folders.first(3).each do |folder|
  puts "  • #{folder.name} (ID: #{folder.id})"
  puts "    Path: #{folder.relativePath} | Child count: #{folder.child_count}"
  puts "    Can save: #{folder.can_save} | Pinned: #{folder.is_pinned}"
end
puts ""
# Get files from first folder with content
if folders.folders.any?
  folder_with_content = folders.folders.find { |f| f.child_count.to_i > 0 }
  if folder_with_content
    folder_files = client.get_folder_files(folder_with_content.id, include_folders: "Y")
    puts "📁 Folder Files:"
    puts "  Folder: #{folder_files.name} | Total: #{folder_files.total_count}"
    puts "  Role: #{folder_files.role_name} | Upload enabled: #{folder_files.show_in_upload}"
  end
end
puts ""
# Get user tasks
tasks = client.get_tasks(filter: "Pending_Tasks", page: 1, limit: 3)
puts "📋 User Tasks:"
puts "  Total tasks: #{tasks.tasks.task.length}"
puts ""
# Display first few tasks
puts "📋 Recent Tasks:"
tasks.tasks.task.first(3).each do |task|
  puts "  • #{task.task_title} (ID: #{task.id})"
  puts "    Status: #{task.status} | Assigned to: #{task.assigned_to_name}"
  puts "    Due: #{task.due_on ? Time.at(task.due_on.to_i).strftime('%Y-%m-%d') : 'None'}"
  puts "    Is overdue: #{task.is_overdue} | Priority: #{task.personal_priority}"
end
puts ""
# Get detailed information for the first task
if tasks.tasks.task.any?
  first_task = tasks.tasks.task.first
  task_id = first_task.is_a?(Array) ? first_task[1] : first_task.id
  task_details = client.get_task_details(task_id)
  puts "📋 Task Details:"
  puts "  Task: #{task_details.task.task_title} (ID: #{task_details.task.id})"
  puts "  Status: #{task_details.task.status} | Bucket: #{task_details.task.bucket}"
  puts "  Assigned to: #{task_details.task.assigned_to_name} | Created by: #{task_details.task.creator_name}"
  puts "  Due: #{task_details.task.due_on ? Time.at(task_details.task.due_on.to_i).strftime('%Y-%m-%d') : 'None'}"
  puts "  Is overdue: #{task_details.task.is_overdue} | Priority: #{task_details.task.personal_priority}"
  puts "  Milestone: #{task_details.task.milestone_name || 'None'}"
  puts "  Project: #{task_details.task.conversation_name}"
  puts "  Visibility: #{task_details.task.visibility}"
  # Show reviewers
  if task_details.task.reviewers && task_details.task.reviewers.reviewer
    reviewers = task_details.task.reviewers.reviewer
    puts "  Reviewers: #{reviewers.length} reviewers"
  end
  # Show next actions
  if task_details.task.next_actions && task_details.task.next_actions.action
    actions = task_details.task.next_actions.action
    puts "  Available actions: #{actions.join(', ')}"
  end
end
puts ""
# Get user wikis
wikis = client.get_wikis(mode: "my", limit: 5, offset: 0)
puts "📚 User Wikis:"
puts "  Total wikis: #{wikis.wikis.length}"
puts ""
# Display first few wikis
puts "📚 Recent Wikis:"
wikis.wikis.first(3).each do |wiki|
  puts "  • #{wiki.title} (ID: #{wiki.id})"
  puts "    Updated: #{Time.at(wiki.updated_at.to_i).strftime('%Y-%m-%d')}"
  puts "    Children: #{wiki.children_count} | Can edit: #{wiki.can_edit}"
  puts "    Conversation: #{wiki.conversation_name || 'None'} (ID: #{wiki.conversation_id})"
  puts "    Is draft: #{wiki.is_draft} | PDF access: #{wiki.generate_pdf_access}"
end
puts ""
# Get detailed information for the first wiki
if wikis.wikis.any?
  first_wiki = wikis.wikis.first
  wiki_details = client.get_wiki_details(first_wiki.id)
  puts "📚 Wiki Details:"
  puts "  Wiki: #{wiki_details.wiki.details.title} (ID: #{wiki_details.wiki.details.id})"
  puts "  Status: #{wiki_details.wiki.details.status} | Platform: #{wiki_details.wiki.details.platform}"
  puts "  Created by: #{wiki_details.wiki.details.created_by_name} | Updated by: #{wiki_details.wiki.details.updated_by_name}"
  puts "  Read count: #{wiki_details.wiki.details.total_read_count} | Children: #{wiki_details.wiki.details.children_count}"
  puts "  Conversation: #{wiki_details.wiki.details.conversation_name}"
  puts "  Edit permissions: #{wiki_details.wiki.details.} | Commentable: #{wiki_details.wiki.details.is_commentable}"
  puts "  Generate PDF access: #{wiki_details.wiki.details.generate_pdf_access} | Show TOC: #{wiki_details.wiki.details.show_toc}"
  puts "  Archived: #{wiki_details.wiki.details.archived} | Is draft: #{wiki_details.wiki.is_draft}"
  # Show permissions
  puts "  Permissions: Comment: #{wiki_details.wiki.can_comment}, Edit: #{wiki_details.wiki.can_edit}, Delete: #{wiki_details.wiki.can_delete}"
  # Show reactions
  if wiki_details.wiki.reactions
    reactions = wiki_details.wiki.reactions
    puts "  Reactions: Like: #{reactions.like_count}, Superlike: #{reactions.superlike_count}"
  end
  # Show comment count
  puts "  Comment count: #{wiki_details.wiki.comment_count}"
end
puts ""
# Get core value tags
 = client.
# Display core value tags
puts "🎯 Core Value Tags:"
..each do |tag|
  puts "  • #{tag.name} (ID: #{tag.id})"
  puts "    Color: ##{tag.color}"
end
puts ""
# Get leaderboard information
leaderboard = client.leaderboard_info
# Display leaderboard if available
if leaderboard.leaderboard_info
  puts "🏅 User Leaderboard:"
  leaderboard.leaderboard_info.user_info.each do |user|
    puts "  #{user.rank}. #{user.name} - #{user.award_count} awards"
  end
  puts ""
  puts "🏆 Team Leaderboard:"
  leaderboard.leaderboard_info.team_info.each do |team|
    puts "  #{team.rank}. #{team.name} - #{team.award_count} awards"
  end
else
  puts "📊 No leaderboard data configured"
end
Error Handling with Clean Responses
begin
  user = client.me
  # Clean dot notation access
  puts "Welcome, #{user.user_profile.minimal_profile.name}!"
rescue MangoApps::AuthenticationError => e
  puts "Authentication failed: #{e.}"
  # Redirect to OAuth flow
rescue MangoApps::APIError => e
  puts "API error: #{e.}"
  puts "Status: #{e.status_code}"
rescue MangoApps::RateLimitError => e
  puts "Rate limited: #{e.}"
  # Implement backoff strategy
end
Error Handling
The SDK provides specific exception types for different error scenarios:
begin
  posts = client.posts_list
rescue MangoApps::AuthenticationError => e
  puts "Authentication failed: #{e.}"
rescue MangoApps::APIError => e
  puts "API error: #{e.}"
rescue MangoApps::RateLimitError => e
  puts "Rate limited: #{e.}"
end
# OAuth-specific error handling
begin
  userinfo = client.get_userinfo
rescue MangoApps::TokenExpiredError => e
  puts "OAuth token expired: #{e.}"
  # Refresh token or redirect to OAuth flow
rescue MangoApps::APIError => e
  puts "OAuth userinfo error: #{e.}"
end
Available Exception Types
MangoApps::Error- Base error classMangoApps::APIError- General API errorsMangoApps::AuthenticationError- Authentication failuresMangoApps::TokenExpiredError- Token expirationMangoApps::DiscoveryError- OAuth discovery endpoint errorsMangoApps::TokenExchangeError- OAuth token exchange errorsMangoApps::BadRequestError- 400 errorsMangoApps::UnauthorizedError- 401 errorsMangoApps::ForbiddenError- 403 errorsMangoApps::NotFoundError- 404 errorsMangoApps::RateLimitError- 429 errorsMangoApps::ServerError- 5xx errors
Configuration Options
config = MangoApps::Config.new(
  domain: "yourdomain.mangoapps.com",
  client_id: "your_client_id",
  client_secret: "your_client_secret",
  redirect_uri: "https://localhost:3000/oauth/callback",
  scope: "openid profile email",
  timeout: 30,
  open_timeout: 10,
  logger: Logger.new(STDOUT)
)
# OAuth-specific configuration
# - All OAuth endpoints automatically use HTTPS
# - Automatic redirect handling for 301/302 responses
# - SSL certificate verification enabled
Current API Coverage
- ✅ Learn Module: Course catalog, categories, course details, and my learning (4 endpoints)
 - ✅ Users Module: User profile and authentication (1 endpoint)
 - ✅ Recognitions Module: Award categories, get awards list, get profile awards, core value tags, and leaderboard info (5 endpoints)
 - ✅ Notifications Module: My priority items for requests, events, quizzes, surveys, tasks, and todos, and user notifications with unread counts (2 endpoints)
 - ✅ Feeds Module: User activity feeds with unread counts and feed details (1 endpoint)
 - ✅ Posts Module: Get all posts with filtering options and get post by ID (2 endpoints)
 - ✅ Libraries Module: Get user's document libraries with categories and items, get library categories by ID, and get library items by library and category ID (3 endpoints)
 - ✅ Trackers Module: Get user's trackers with submission dates and conversation details (1 endpoint)
 - ✅ Attachments Module: Get user's file folders with permissions and metadata, and get files and folders inside specific folders (2 endpoints)
 - ✅ Tasks Module: Get user's tasks with filtering, pagination, and detailed task information, and get detailed information for specific tasks (2 endpoints)
 - ✅ Wikis Module: Get user's wikis with filtering, pagination, and detailed wiki information, and get detailed information for specific wikis (2 endpoints)
 - ✅ Error Handling: Comprehensive error logging and testing
 - ✅ OAuth Flow: Token management, refresh, and userinfo endpoint
 - ✅ Internal API Auth: Alternative authentication using API keys
 - ✅ Auto Detection: Automatic authentication method detection and prioritization
 - ✅ Pagination Support: Optional page and limit parameters for all list APIs
 - ✅ HTTPS Security: Automatic HTTPS enforcement with redirect handling
 
Total: 26 API endpoints across 11 modules + OAuth + Internal API + Auto Detection + Pagination
Contributing
- Fork the repository
 - Create a feature branch
 - Write real tests first (no mocking)
 - Implement the feature
 - Ensure all tests pass
 - Submit a pull request
 
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support
- Documentation: RubyDoc
 - Issues: GitHub Issues
 - MangoApps: Official Website
 
Changelog
See CHANGELOG.md for a list of changes and version history.