alumni_lookup

API Documentation

Updated: November 26, 2025
Purpose: Document all API endpoints in the alumni_lookup application.


Table of Contents

  1. Overview
  2. API Endpoints
  3. Authentication
  4. Response Formats
  5. Future Considerations

Overview

The alumni_lookup application provides a set of internal JSON APIs primarily used by JavaScript components for dynamic UI features like autocomplete, filtering, and data loading.

Base URL: /api/

Current Status: These APIs are internal-only and not intended for external consumption.

Available Endpoints

Endpoint Method Purpose
/api/affinities GET Fetch affinities by category
/api/alumni GET Search alumni by name
/api/majors GET Fetch majors by college
/api/activity_descriptions GET Fetch activity descriptions

API Endpoints

1. Affinities API

Fetch affinity options filtered by category for dropdown population.

Endpoint: GET /api/affinities

Parameters:

Parameter Type Required Description
category string Yes Affinity category filter

Valid Categories:

Example Request:

GET /api/affinities?category=Athletics

Example Response:

[
  {
    "affinity_code": "BASEBALL",
    "name": "Baseball"
  },
  {
    "affinity_code": "BBALL",
    "name": "Basketball"
  }
]

Controller: Api::AffinitiesController

class Api::AffinitiesController < ApplicationController
  def index
    category = params[:category]
    affinities = Affinity.where(category: category).order(:name)
    render json: affinities.select(:affinity_code, :name)
  end
end

2. Alumni API

Search alumni by name for autocomplete/typeahead functionality.

Endpoint: GET /api/alumni

Parameters:

Parameter Type Required Description
name string Yes Name search query

Example Request:

GET /api/alumni?name=John

Example Response:

[
  {
    "buid": "B00123456",
    "contact_id": "C-123456789",
    "last_name": "Doe",
    "display_name": "John Doe",
    "recent_degree": {
      "major_desc": "Accounting",
      "college_name": "Jack C. Massey College of Business",
      "degree_code": "BS",
      "degree_date": "2020-05-09"
    }
  }
]

Response Fields:

Field Type Description
buid string Unique alumni identifier
contact_id string CRM contact ID (format: C-000000000)
last_name string Alumni last name
display_name string Full formatted name (via display_name method)
recent_degree object Most recent degree information

Error Response (missing parameter):

{
  "error": "Name parameter is required"
}

HTTP Status: 400 Bad Request

Controller: Api::AlumniController

class Api::AlumniController < ApplicationController
  def index
    if params[:name].present?
      alumni = Alumni.filter_by_name(params[:name])
                     .order(:last_name, :first_name)
                     .limit(10)
      render json: alumni.as_json(
        only: [:buid, :contact_id, :last_name],
        methods: [:display_name],
        include: {
          recent_degree: { only: [:major_desc, :college_name, :degree_code, :degree_date] }
        }
      )
    else
      render json: { error: "Name parameter is required" }, status: :bad_request
    end
  end
end

Notes:


3. Majors API

Fetch majors filtered by college code for cascading dropdown population.

Endpoint: GET /api/majors

Parameters:

Parameter Type Required Description
college string Yes College code filter

Example Request:

GET /api/majors?college=BUS

Example Response:

[
  {
    "dept": "ACCT",
    "dept_desc": "Accounting",
    "major_code": "ACCT",
    "major_desc": "Accounting",
    "active": true
  },
  {
    "dept": "FIN",
    "dept_desc": "Finance",
    "major_code": "FIN",
    "major_desc": "Finance",
    "active": true
  }
]

Response Fields:

Field Type Description
dept string Department code
dept_desc string Department description
major_code string Unique major identifier
major_desc string Major description
active boolean Whether major is currently active

Controller: Api::MajorsController

class Api::MajorsController < ApplicationController
  def index
    college = params[:college]
    majors = Major.where(college_code: college).order(:dept, :major_desc)
    render json: majors.select(:dept, :dept_desc, :major_code, :major_desc, :active)
  end
end

4. Activity Descriptions API

Fetch distinct activity descriptions for filtering engagement activities.

Endpoint: GET /api/activity_descriptions

Parameters:

Parameter Type Required Description
activity_code string Yes Activity type code
start_date date No Filter start date
end_date date No Filter end date
college string No College code filter
year integer No Fiscal year filter

Example Request:

GET /api/activity_descriptions?activity_code=event_attended&start_date=2024-01-01&end_date=2024-12-31

Example Response:

[
  "Homecoming 2024",
  "Alumni Awards Gala",
  "Career Fair",
  "Reunion Weekend"
]

Response: Array of distinct description strings, sorted alphabetically.

Controller: Api::ActivityDescriptionsController

class Api::ActivityDescriptionsController < ApplicationController
  def index
    activity_code = params[:activity_code]
    start_date = params[:start_date]
    end_date = params[:end_date]
    college = params[:college]
    year = params[:year]

    alumni_scope = Alumni.all
    alumni_scope = alumni_scope.filter_by_college(college)
    alumni_scope = alumni_scope.filter_by_fiscal_year(year)

    buids = alumni_scope.pluck(:buid)

    descriptions = EngagementActivity
      .where(buid: buids)
      .where(activity_code: activity_code)
      .where(engagement_date: start_date..end_date)
      .where.not(description: [nil, ""])
      .distinct
      .order(:description)
      .pluck(:description)

    render json: descriptions
  end
end

Notes:


Authentication

Current State

None of the API endpoints currently require authentication.

These endpoints are intended for internal JavaScript consumption and are accessed from authenticated pages. The assumption is that the user has already authenticated to access the parent page.

Security Considerations

Risk Mitigation
Data exposure APIs return limited fields, no sensitive data
Abuse potential Low - data is publicly available alumni info
Rate limiting None currently (consider adding)
  1. Add authentication for all API endpoints
  2. Add rate limiting to prevent abuse
  3. Add CSRF protection for state-changing operations (if any added)
# Recommended pattern for authenticated APIs
class Api::BaseController < ApplicationController
  before_action :authenticate_user!
  # or for token-based auth:
  # before_action :authenticate_api_token!
end

Response Formats

Success Responses

All endpoints return JSON with appropriate HTTP status codes:

Status Meaning
200 OK Request successful
400 Bad Request Missing required parameters

Error Responses

{
  "error": "Error message description"
}

Data Types

Type Format Example
Date ISO 8601 "2024-05-09"
Boolean JSON boolean true, false
ID (buid) String "B00123456"
Contact ID String "C-123456789"

Future Considerations

Potential Expansion for External Use

If these APIs are exposed externally in the future, consider:

  1. Versioning
    /api/v1/alumni
    /api/v1/affinities
    
  2. Authentication
    • API tokens for external integrations
    • OAuth 2.0 for champion portal and mobile apps
    • JWT tokens for stateless mobile authentication
  3. Rate Limiting
    • Per-IP or per-token limits
    • Throttling middleware (e.g., rack-attack)
  4. Documentation
    • OpenAPI/Swagger specification
    • Interactive API explorer
  5. Additional Endpoints
    POST /api/v1/champion_signups  # External signup submission
    GET  /api/v1/champions/:id     # Champion profile (authenticated)
    PUT  /api/v1/champions/:id     # Update champion (authenticated)
    

Mobile App Considerations (iOS/Android)

If a native mobile app is developed in the future, the API should support:

Authentication for Mobile

| Approach | Description | Pros/Cons | |———-|————-|———–| | OAuth 2.0 + JWT | Industry standard for mobile | ✅ Secure, refresh tokens, widely supported | | API Keys | Simple token-based | ⚠️ Less secure, no expiration handling | | Device Tokens | Per-device authentication | ✅ Good for push notifications integration |

Recommended: OAuth 2.0 with JWT tokens and refresh token flow:

POST /api/v1/auth/token        # Exchange credentials for tokens
POST /api/v1/auth/refresh      # Refresh expired access token
DELETE /api/v1/auth/revoke     # Revoke tokens (logout)

Mobile-Specific Endpoints

# Device registration for push notifications
POST /api/v1/devices
DELETE /api/v1/devices/:id

# Offline-friendly data sync
GET /api/v1/sync?since=<timestamp>    # Delta updates since last sync
GET /api/v1/champions/:id/offline     # Bundled data for offline access

# App metadata
GET /api/v1/app/config                # Feature flags, min version, etc.
GET /api/v1/app/version               # Check for required updates

Push Notifications (Primary Mobile Feature)

Push notifications are a primary driver for building a native mobile app. They enable direct, timely communication with champions about events, opportunities, and engagement.

Notification Types

| Type | Trigger | Priority | Example | |——|———|———-|———| | Event Reminder | Upcoming RSVP’d event | High | “Homecoming is tomorrow! See you at 2pm.” | | New Event | Event published in champion’s area | Medium | “New volunteer opportunity in Nashville” | | Engagement Milestone | Champion reaches achievement | Low | “You’ve attended 5 events this year! 🎉” | | Direct Message | Staff sends targeted message | High | “Quick question about your availability…” | | Campaign Update | Major initiative announcement | Medium | “Campaign goal reached! Thank you!” |

Device Registration Endpoints
# Register device for push notifications
POST /api/v1/devices
{
  "device_token": "abc123...",      # APNs token (iOS) or FCM token (Android)
  "platform": "ios",                 # "ios" or "android"
  "app_version": "1.2.0",
  "os_version": "17.1",
  "device_model": "iPhone 15 Pro"
}

# Update notification preferences
PUT /api/v1/devices/:id/preferences
{
  "events": true,
  "reminders": true,
  "messages": true,
  "marketing": false
}

# Remove device (logout/uninstall)
DELETE /api/v1/devices/:id
Notification Delivery Endpoints
# Get notification history (for in-app notification center)
GET /api/v1/notifications
GET /api/v1/notifications/unread_count

# Mark notifications as read
POST /api/v1/notifications/:id/read
POST /api/v1/notifications/mark_all_read
Server-Side Infrastructure (Future)

| Component | Purpose | Options | |———–|———|———| | APNs Integration | iOS push delivery | Direct APNs, or service like Firebase/OneSignal | | FCM Integration | Android push delivery | Firebase Cloud Messaging | | Job Queue | Async notification sending | Sidekiq, GoodJob | | Notification Model | Track sent/read status | New Notification model | | Preferences | User opt-in/out settings | New NotificationPreference model |

Badge Management
# iOS badge count management
GET /api/v1/notifications/badge_count
POST /api/v1/notifications/clear_badge
Rich Notifications (iOS)

Support for rich notifications with images, action buttons:

{
  "aps": {
    "alert": {
      "title": "New Event Near You",
      "body": "Nashville Alumni Mixer - Dec 15"
    },
    "badge": 3,
    "sound": "default",
    "mutable-content": 1
  },
  "data": {
    "type": "event",
    "event_id": "123",
    "image_url": "https://..."
  }
}

Response Design for Mobile

// Example mobile-friendly response
{
  "data": {
    "id": "B00123456",
    "type": "champion",
    "attributes": { ... },
    "relationships": { ... }
  },
  "meta": {
    "updated_at": "2025-11-26T12:00:00Z",
    "sync_token": "abc123"
  }
}

iOS-Specific Considerations

| Feature | API Requirement | |———|—————–| | Push Notifications | APNs device token registration endpoint | | Background Refresh | Efficient delta sync endpoint | | Sign in with Apple | OAuth integration with Apple ID | | App Clips | Lightweight authentication flow | | Widgets | Minimal data endpoints for widget refresh |

Security for Mobile

Champion Portal API (Conceptual)

Future authenticated endpoints for the champion portal:

Endpoint Method Purpose
/api/v1/profile GET Get current champion profile
/api/v1/profile PUT Update champion profile
/api/v1/events GET List upcoming events
/api/v1/events/:id/rsvp POST RSVP to an event
/api/v1/activities GET Champion’s activity history


Last updated: November 26, 2025