Skip to main content

Introduction

The BoxApp API is built on Supabase, providing a powerful PostgreSQL-based backend with real-time capabilities, authentication, and row-level security. The API enables you to manage all aspects of your CrossFit gym, including members, classes, workouts, competitions, and more.

Base URL

The API base URL is your Supabase project URL:
https://your-project.supabase.co

Authentication

All API requests require authentication using Supabase Auth. You must include your authentication token in the request headers. See the Authentication page for detailed information on signing in, signing up, and managing user sessions.

Client Initialization

To interact with the BoxApp API, you initialize the Supabase client with your project credentials:
import { createClient } from '@supabase/supabase-js';
import { Database } from '@/types/supabase';

const supabaseUrl = process.env.VITE_SUPABASE_URL;
const supabaseAnonKey = process.env.VITE_SUPABASE_ANON_KEY;

export const supabase = createClient<Database>(supabaseUrl, supabaseAnonKey);
The Database type provides full TypeScript type safety for all tables, columns, and relationships in your database.

Environment Variables

You need to configure the following environment variables:
VITE_SUPABASE_URL
string
required
Your Supabase project URL (e.g., https://xxxxx.supabase.co)
VITE_SUPABASE_ANON_KEY
string
required
Your Supabase anonymous/public API key. This key is safe to use in client-side code and respects row-level security policies.

Core Resources

The BoxApp API provides access to the following core resources:

Profiles

User profiles with role-based access control (admin, coach, athlete).
type Profile = Database['public']['Tables']['profiles']['Row'];

Boxes

Gym/box configurations including branding, themes, and subscription status.
type Box = Database['public']['Tables']['boxes']['Row'];

Classes & Sessions

Class schedules, sessions, and bookings for gym members.
type Class = Database['public']['Tables']['classes']['Row'];
type Session = Database['public']['Tables']['sessions']['Row'];
type Booking = Database['public']['Tables']['bookings']['Row'];

Workouts (WODs)

Daily workouts with structured blocks and programming.
type WOD = Database['public']['Tables']['wods']['Row'];

Competitions

Comprehensive competition management including events, divisions, participants, scoring, and leaderboards.
type Competition = Database['public']['Tables']['competitions']['Row'];
type CompetitionEvent = Database['public']['Tables']['competition_events']['Row'];
type CompetitionParticipant = Database['public']['Tables']['competition_participants']['Row'];

Memberships & Billing

Membership plans, invoices, and payment tracking.
type Plan = Database['public']['Tables']['plans']['Row'];
type Membership = Database['public']['Tables']['memberships']['Row'];
type Invoice = Database['public']['Tables']['invoices']['Row'];

Inventory

Equipment and supplies inventory management.
type Item = Database['public']['Tables']['items']['Row'];

Making Requests

The Supabase client provides a fluent API for querying and mutating data:

Fetching Data

// Get all profiles in the current box
const { data, error } = await supabase
  .from('profiles')
  .select('*')
  .eq('box_id', boxId);

Inserting Data

// Create a new class
const { data, error } = await supabase
  .from('classes')
  .insert({
    name: 'CrossFit Fundamentals',
    capacity: 12,
    duration_minutes: 60,
    start_time: '2026-03-05T10:00:00',
    end_time: '2026-03-05T11:00:00'
  });

Updating Data

// Update a user's profile
const { data, error } = await supabase
  .from('profiles')
  .update({ first_name: 'John', last_name: 'Doe' })
  .eq('id', userId);

Deleting Data

// Cancel a class
const { data, error } = await supabase
  .from('classes')
  .update({ is_canceled: true })
  .eq('id', classId);

Response Format

All API operations return a response object with the following structure:
data
T | T[] | null
The returned data from the query. Will be null if an error occurred.
error
PostgrestError | null
An error object if the request failed, otherwise null.

Error Handling

Always check for errors in your API responses:
const { data, error } = await supabase
  .from('profiles')
  .select('*')
  .eq('id', userId)
  .single();

if (error) {
  console.error('Error fetching profile:', error.message);
  return;
}

// Use data safely
console.log('Profile:', data);
The .single() modifier expects exactly one row. If zero or multiple rows are returned, it will return an error.

Real-time Subscriptions

Subscribe to real-time changes in your database:
const subscription = supabase
  .channel('custom-channel')
  .on(
    'postgres_changes',
    {
      event: '*',
      schema: 'public',
      table: 'classes'
    },
    (payload) => {
      console.log('Change received:', payload);
    }
  )
  .subscribe();

// Cleanup
subscription.unsubscribe();

Multi-tenancy

BoxApp implements multi-tenancy through the box_id field. All queries automatically filter data based on the authenticated user’s box association through row-level security policies.
You don’t need to manually filter by box_id in most cases - RLS policies handle this automatically based on the authenticated user’s profile.

Rate Limits

Supabase enforces rate limits based on your subscription plan. Monitor your usage through the Supabase dashboard.

TypeScript Support

The BoxApp API provides comprehensive TypeScript types generated from your database schema:
import { Database } from '@/types/supabase';

// Table row types
type Profile = Database['public']['Tables']['profiles']['Row'];

// Insert types (fields with defaults are optional)
type ProfileInsert = Database['public']['Tables']['profiles']['Insert'];

// Update types (all fields optional)
type ProfileUpdate = Database['public']['Tables']['profiles']['Update'];

// Enum types
type WodType = Database['public']['Enums']['wod_type'];
type ScoreStatus = Database['public']['Enums']['score_status'];

Next Steps

  • Read the Authentication guide to learn about user management
  • Explore the Supabase Documentation for advanced features
  • Review row-level security policies in your Supabase dashboard

Build docs developers (and LLMs) love