Presently API

A read-only REST API for pulling your studio data into external systems, dashboards, and integrations. Bearer-token auth via Laravel Sanctum.

API tokens are generated from the Profile page inside your Presently tenant.

Presently API Documentation

Overview

Presently provides a RESTful API for programmatic access to your studio data. The API uses Laravel Sanctum for authentication via personal access tokens.

Authentication

Creating an API Token

  1. Log in to your Presently tenant admin panel
  2. Navigate to My Profile (/profile)
  3. Scroll down to the "API Tokens" section
  4. Click "Create Token"
  5. Give your token a descriptive name (e.g., "Mobile App", "Integration")
  6. Click the token field to copy it - it won't be shown again!

Using Your Token

Include your API token in the Authorization header of all API requests:

curl -H "Authorization: Bearer YOUR_API_TOKEN" \
     https://your-tenant.usepresently.com/api/user

Important: Keep your API tokens secure. Never commit them to version control or share them publicly.

Base URL

All API requests should be made to:

https://your-tenant.usepresently.com/api/

Replace your-tenant with your actual tenant slug.

Endpoints

User Information

Get Current User

Returns information about the authenticated user.

GET /api/user

Response:

{
  "id": 1,
  "name": "John Doe",
  "email": "john@example.com",
  "tenant_id": 1,
  "role": "tenant_admin",
  "is_active": true,
  "created_at": "2025-01-01T00:00:00.000000Z",
  "tenant": {
    "id": 1,
    "name": "Dance Studio",
    "slug": "dancestudio"
  }
}

Families

List Families

Returns a paginated list of families.

GET /api/families

Query Parameters:

  • page (integer, optional): Page number for pagination (default: 1)

Response:

{
  "data": [
    {
      "id": 1,
      "name": "Smith Family",
      "primary_contact_first_name": "Jane",
      "primary_contact_last_name": "Smith",
      "email": "jane@example.com",
      "phone": "(555) 123-4567",
      "students": [
        {
          "id": 1,
          "first_name": "Emily",
          "last_name": "Smith",
          "date_of_birth": "2010-05-15"
        }
      ]
    }
  ],
  "links": { ... },
  "meta": { ... }
}

Get Single Family

Returns details for a specific family.

GET /api/families/{family_id}

Response:

{
  "id": 1,
  "name": "Smith Family",
  "students": [ ... ],
  "enrollments": [ ... ]
}

Students

List Students

Returns a paginated list of students.

GET /api/students

Query Parameters:

  • page (integer, optional): Page number for pagination (default: 1)

Response:

{
  "data": [
    {
      "id": 1,
      "first_name": "Emily",
      "last_name": "Smith",
      "date_of_birth": "2010-05-15",
      "family": {
        "id": 1,
        "name": "Smith Family"
      }
    }
  ],
  "links": { ... },
  "meta": { ... }
}

Get Single Student

Returns details for a specific student.

GET /api/students/{student_id}

Response:

{
  "id": 1,
  "first_name": "Emily",
  "last_name": "Smith",
  "family": { ... },
  "enrollments": [ ... ]
}

Classes

List Classes

Returns a paginated list of classes.

GET /api/classes

Query Parameters:

  • page (integer, optional): Page number for pagination (default: 1)

Response:

{
  "data": [
    {
      "id": 1,
      "name": "Ballet Level 1",
      "season": {
        "id": 1,
        "name": "Fall 2025"
      },
      "class_type": {
        "id": 1,
        "name": "Ballet"
      },
      "location": {
        "id": 1,
        "name": "Studio A"
      },
      "schedules": [
        {
          "day_of_week": "Monday",
          "start_time": "16:00:00",
          "end_time": "17:00:00"
        }
      ],
      "instructors": [
        {
          "id": 1,
          "first_name": "Sarah",
          "last_name": "Johnson"
        }
      ]
    }
  ],
  "links": { ... },
  "meta": { ... }
}

Get Single Class

Returns details for a specific class including enrolled students.

GET /api/classes/{class_id}

Response:

{
  "id": 1,
  "name": "Ballet Level 1",
  "season": { ... },
  "enrollments": [
    {
      "id": 1,
      "student": {
        "id": 1,
        "first_name": "Emily",
        "last_name": "Smith"
      }
    }
  ]
}

Enrollments

List Enrollments

Returns a paginated list of enrollments.

GET /api/enrollments

Query Parameters:

  • page (integer, optional): Page number for pagination (default: 1)

Response:

{
  "data": [
    {
      "id": 1,
      "status": "active",
      "student": {
        "id": 1,
        "first_name": "Emily",
        "last_name": "Smith"
      },
      "class": {
        "id": 1,
        "name": "Ballet Level 1"
      },
      "family": {
        "id": 1,
        "name": "Smith Family"
      }
    }
  ],
  "links": { ... },
  "meta": { ... }
}

Get Single Enrollment

Returns details for a specific enrollment.

GET /api/enrollments/{enrollment_id}

Ledger Entries

List Ledger Entries

Returns a paginated list of ledger entries.

GET /api/ledger-entries

Query Parameters:

  • page (integer, optional): Page number for pagination (default: 1)

Response:

{
  "data": [
    {
      "id": 1,
      "family_id": 1,
      "date": "2025-01-15",
      "type": "charge",
      "amount": 150.00,
      "description": "January 2025 Tuition",
      "family": {
        "id": 1,
        "name": "Smith Family"
      },
      "line_items": [
        {
          "id": 1,
          "amount": 150.00,
          "enrollment": {
            "id": 1,
            "student": {...},
            "class": {...}
          }
        }
      ]
    }
  ],
  "links": { ... },
  "meta": { ... }
}

Get Single Ledger Entry

Returns details for a specific ledger entry.

GET /api/ledger-entries/{ledger_entry_id}

Get Family Ledger Entries

Returns all ledger entries for a specific family.

GET /api/families/{family_id}/ledger-entries

Query Parameters:

  • page (integer, optional): Page number for pagination (default: 1)

Events

List Events

Returns a paginated list of events (performances, recitals).

GET /api/events

Query Parameters:

  • page (integer, optional): Page number for pagination (default: 1)

Response:

{
  "data": [
    {
      "id": 1,
      "name": "Spring Recital 2025",
      "date": "2025-05-20",
      "start_time": "18:00:00",
      "end_time": "20:00:00",
      "season": {
        "id": 1,
        "name": "Spring 2025"
      },
      "location": {
        "id": 1,
        "name": "Main Theater"
      }
    }
  ],
  "links": { ... },
  "meta": { ... }
}

Get Single Event

Returns details for a specific event including lineup and intermissions.

GET /api/events/{event_id}

Response:

{
  "id": 1,
  "name": "Spring Recital 2025",
  "date": "2025-05-20",
  "lineup_items": [
    {
      "id": 1,
      "order": 1,
      "class": {
        "id": 1,
        "name": "Ballet Level 1"
      }
    }
  ],
  "intermissions": [
    {
      "id": 1,
      "order": 5,
      "title": "Intermission",
      "duration": 15
    }
  ]
}

Costumes

List Costumes

Returns a paginated list of all costumes.

GET /api/costumes

Query Parameters:

  • page (integer, optional): Page number for pagination (default: 1)

Response:

{
  "data": [
    {
      "id": 1,
      "name": "Pink Tutu",
      "style_number": "PT-100",
      "company": {
        "id": 1,
        "name": "Dance Costume Co."
      }
    }
  ],
  "links": { ... },
  "meta": { ... }
}

Get Single Costume

Returns details for a specific costume including available sizes and prices.

GET /api/costumes/{costume_id}

Get Family Costumes

Returns all costume assignments for students in a family.

GET /api/families/{family_id}/costumes

Response:

{
  "family": {
    "id": 1,
    "name": "Smith Family"
  },
  "students": [
    {
      "id": 1,
      "first_name": "Emily",
      "last_name": "Smith",
      "costumes": [
        {
          "id": 1,
          "costume": {
            "id": 1,
            "name": "Pink Tutu",
            "style_number": "PT-100"
          },
          "company_size": {
            "id": 1,
            "size": "Medium Child"
          },
          "quantity": 1,
          "is_committed": true,
          "committed_at": "2025-01-15T10:30:00.000000Z"
        }
      ]
    }
  ]
}

Instructors

List Instructors

GET /api/instructors

Response:

{
  "data": [
    {
      "id": 1,
      "first_name": "Sarah",
      "last_name": "Johnson",
      "display_name": "Miss Sarah",
      "email": "sarah@example.com",
      "phone": "(555) 000-0000",
      "is_active": true
    }
  ],
  "links": { ... },
  "meta": { ... }
}

Get Single Instructor

GET /api/instructors/{instructor_id}

Returns the instructor with their assigned classes.


Seasons

List Seasons

GET /api/seasons

Response:

{
  "data": [
    {
      "id": 1,
      "name": "Fall 2025",
      "start_date": "2025-09-01",
      "end_date": "2025-12-15",
      "is_active": true
    }
  ]
}

Get Single Season

GET /api/seasons/{season_id}

Returns the season with all its classes.


Class Types

List Class Types

GET /api/class-types

Returns class types with a summary of their attached rate group. Rate details are on the singular endpoint.

Get Single Class Type

GET /api/class-types/{class_type_id}

Returns the class type with the full rate group and every rate in it.


Class Schedules

List Class Schedules

GET /api/class-schedules

Returns every scheduled day/time slot across all classes, with the parent class and its location on each row.

Get Single Class Schedule

GET /api/class-schedules/{schedule_id}

Locations

List Locations

GET /api/locations

Get Single Location

GET /api/locations/{location_id}

Rate Groups

List Rate Groups

GET /api/rate-groups

Returns rate groups with all their rates inlined.

Get Single Rate Group

GET /api/rate-groups/{rate_group_id}

Returns the rate group with its rates AND sibling discounts.

List Rates for a Rate Group

GET /api/rate-groups/{rate_group_id}/rates

Just the rate rows for the group.

List Sibling Discounts for a Rate Group

GET /api/rate-groups/{rate_group_id}/sibling-discounts

Just the sibling-discount rows for the group.


Holidays

List Holidays

GET /api/holidays

Ordered by date.

Get Single Holiday

GET /api/holidays/{holiday_id}

Ledger Categories

List Ledger Categories

GET /api/ledger-categories

Categories that ledger entries can be tagged with (Tuition, Registration, Boutique, Late Fee, etc.).

Get Single Ledger Category

GET /api/ledger-categories/{category_id}

Family Payment Methods

List a Family's Payment Methods

GET /api/families/{family_id}/payment-methods

Returns every active payment method on file for the family (cards + ACH). No top-level /payment-methods endpoint — payment methods are always fetched per-family for privacy.

Response:

[
  {
    "id": 1,
    "type": "card",
    "brand": "visa",
    "last4": "4242",
    "exp_month": 12,
    "exp_year": 2030,
    "is_autopay": true,
    "is_active": true
  }
]

Attendance

List Attendance

GET /api/attendance

Query Parameters:

  • class_id (integer, optional): Filter to one class
  • student_id (integer, optional): Filter to one student
  • date_from (YYYY-MM-DD, optional): Inclusive lower bound
  • date_to (YYYY-MM-DD, optional): Inclusive upper bound
  • page (integer, optional)

Ordered most-recent first.

Get Single Attendance Record

GET /api/attendance/{attendance_id}

Drop-Ins

List Drop-Ins

GET /api/drop-ins

Get Single Drop-In

GET /api/drop-ins/{drop_in_id}

Makeup Classes

List Makeup Classes

GET /api/makeup-classes

Get Single Makeup

GET /api/makeup-classes/{makeup_id}

Communications

List Communications

GET /api/communications

Every email / SMS the studio has sent, most-recent first.

Get Single Communication

GET /api/communications/{communication_id}

Waivers

List Waivers

GET /api/waivers

Every waiver on the tenant with its season links.

Get Single Waiver

GET /api/waivers/{waiver_id}

Includes every acceptance row (family + timestamp + signature).


Boutique Items

List Boutique Items

GET /api/boutique-items

Response:

{
  "data": [
    {
      "id": 1,
      "name": "Class T-Shirt",
      "price": "20.00",
      "sales_tax_percentage": "8.00",
      "tax_exempt": false,
      "is_active": true,
      "track_inventory": true,
      "quantity_on_hand": 42
    }
  ]
}

Get Single Boutique Item

GET /api/boutique-items/{item_id}

Returns the item with any images attached.


Boutique Sales

List Boutique Sales

GET /api/boutique-sales

Query Parameters:

  • family_id (integer, optional): Filter to one family
  • date_from (ISO 8601 datetime, optional): Sold at or after
  • date_to (ISO 8601 datetime, optional): Sold at or before
  • page (integer, optional)

Ordered most-recent first. Includes the family and boutique item on each row.

Get Single Boutique Sale

GET /api/boutique-sales/{sale_id}

Includes the family, item, and linked ledger entry.


Tags

List Tags

GET /api/tags

Studio-defined tags (applied to families / students / etc.).

Get Single Tag

GET /api/tags/{tag_id}

Custom Fields

List Custom Fields

GET /api/custom-fields

All custom fields defined on the tenant, ordered by target model then display order.

Get Single Custom Field

GET /api/custom-fields/{field_id}

Private Lesson Slots

List Private Lesson Slots

GET /api/private-lesson-slots

Query Parameters:

  • status (string, optional): open, booked, cancelled, etc.
  • instructor_id (integer, optional): Filter to one instructor
  • page (integer, optional)

Get Single Slot

GET /api/private-lesson-slots/{slot_id}

Includes the instructor, location, and any bookings (with student + family).


Private Lesson Bookings

List Private Lesson Bookings

GET /api/private-lesson-bookings

Get Single Booking

GET /api/private-lesson-bookings/{booking_id}

Includes the slot (with instructor + location), the student, and the family.


Error Handling

The API uses standard HTTP status codes:

  • 200 OK: Request succeeded
  • 401 Unauthorized: Missing or invalid API token
  • 403 Forbidden: Valid token but insufficient permissions
  • 404 Not Found: Resource not found
  • 422 Unprocessable Entity: Validation error
  • 500 Internal Server Error: Server error

Error Response Format:

{
  "message": "Unauthenticated."
}

Rate Limiting

API requests are rate-limited to 60 requests per minute per token. If you exceed this limit, you'll receive a 429 Too Many Requests response.


Pagination

List endpoints return paginated results with the following structure:

{
  "data": [ ... ],
  "links": {
    "first": "https://your-tenant.usepresently.com/api/families?page=1",
    "last": "https://your-tenant.usepresently.com/api/families?page=10",
    "prev": null,
    "next": "https://your-tenant.usepresently.com/api/families?page=2"
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 10,
    "per_page": 50,
    "to": 50,
    "total": 500
  }
}

Examples

Python Example

import requests

API_TOKEN = "your_api_token_here"
BASE_URL = "https://your-tenant.usepresently.com/api"

headers = {
    "Authorization": f"Bearer {API_TOKEN}",
    "Accept": "application/json"
}

# Get all families
response = requests.get(f"{BASE_URL}/families", headers=headers)
families = response.json()

print(f"Found {families['meta']['total']} families")

# Get a specific student
student_id = 1
response = requests.get(f"{BASE_URL}/students/{student_id}", headers=headers)
student = response.json()

print(f"Student: {student['first_name']} {student['last_name']}")

JavaScript/Node.js Example

const axios = require('axios');

const API_TOKEN = 'your_api_token_here';
const BASE_URL = 'https://your-tenant.usepresently.com/api';

const api = axios.create({
  baseURL: BASE_URL,
  headers: {
    'Authorization': `Bearer ${API_TOKEN}`,
    'Accept': 'application/json'
  }
});

// Get all classes
api.get('/classes')
  .then(response => {
    console.log(`Found ${response.data.meta.total} classes`);
  })
  .catch(error => {
    console.error('Error:', error.response.data);
  });

// Get a specific family
const familyId = 1;
api.get(`/families/${familyId}`)
  .then(response => {
    console.log(`Family: ${response.data.name}`);
  });

cURL Example

# Get current user
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
     https://your-tenant.usepresently.com/api/user

# List families (page 2)
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
     "https://your-tenant.usepresently.com/api/families?page=2"

# Get specific class
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
     https://your-tenant.usepresently.com/api/classes/1

Security Best Practices

  1. Keep tokens secure: Store API tokens in environment variables, not in code
  2. Use HTTPS: Always use HTTPS for API requests
  3. Rotate tokens: Periodically delete old tokens and create new ones
  4. Principle of least privilege: Create separate tokens for different integrations
  5. Monitor usage: Check "Last Used" timestamps in the API Tokens page

Support

For API support or to request additional endpoints, contact your Presently administrator or visit the Presently documentation.

Ready to try Presently?

Every plan includes API access. Create a tenant, generate a token from your Profile page, and start pulling data in minutes.