> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getparable.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Data model

# Registrations Data Model

## Overview

The Registrations module contains **11 entity tables** and **3 relationship tables** supporting event registration, attendee management, emergency contacts, and signup tracking.

## Complete Schema Reference

This guide provides a comprehensive reference for all Planning Center Registrations tables available in Parable. Understanding this data model will help you write accurate queries and build meaningful reports for your event management needs.

## Visual Data Model

<Tip>
  The diagram below shows the core entities and their relationships in the Registrations module. Use it as a visual reference while exploring the detailed table definitions below.
</Tip>

### Core Entity Relationships

<Frame>
  <img src="https://mintcdn.com/parable/dIkTtcPi0zjaWA0V/diagrams/planning-center/registrations-data-model-01.svg?fit=max&auto=format&n=dIkTtcPi0zjaWA0V&q=85&s=0b7d5e55b0c86f057f2bcfb2e63f05de" alt="Registrations module data model" width="3083" height="1687" data-path="diagrams/planning-center/registrations-data-model-01.svg" />
</Frame>

[Open diagram in new tab →](/diagrams/planning-center/registrations-data-model-01.svg)

### Key Relationships Explained

**Registration Structure:**

* `REGISTRATION` defines an event or program accepting signups
* `CATEGORY` organizes signup options (e.g., T-shirt size, Meal preference)
* `SELECTION_TYPE` provides specific choices within categories

**Signup Flow:**

1. Person creates a `SIGNUP` for a registration
2. `ATTENDEE`(s) are added (self or others)
3. `SIGNUP_TIME`(s) specify when attendees will participate
4. `SIGNUP_LOCATION`(s) define where events occur
5. `EMERGENCY_CONTACT`(s) provide safety information

**Person vs Attendee:**

* `PERSON` is the signup submitter (from People module)
* `ATTENDEE` can be the submitter or someone else (child, guest, etc.)
* One signup can include multiple attendees
* Each attendee has their own emergency contacts

**Time and Location:**

* `SIGNUP_TIME` tracks session/workshop times
* `SIGNUP_LOCATION` tracks event venues
* Both linked to parent signup, not individual attendees
* Supports multi-day, multi-location events

**Generic Relationship Pattern:**

* Campus associations via `registrations_registration_relationships`
* Additional metadata via relationship tables

## Query Requirements

### Schema Prefix

**IMPORTANT:** All tables in the Planning Center Registrations module are in the `planning_center` schema. You MUST prefix all table names with `planning_center.` in your queries.

✅ CORRECT: `SELECT * FROM planning_center.registrations_signups`
❌ INCORRECT: `SELECT * FROM registrations_signups`

### Row Level Security (RLS)

This database uses Row Level Security (RLS) to automatically filter data based on:

* **tenant\_organization\_id**: You only see data for your current organization
* **system\_status**: You only see 'active' records by default

**DO NOT add these filters to your WHERE clause** - they are applied automatically:

* ❌ `WHERE tenant_organization_id = 1` (unnecessary)
* ❌ `WHERE system_status = 'active'` (unnecessary)

The RLS policies ensure you only access data you're authorized to see, making these filters redundant and potentially causing performance issues.

## Entity Tables

### registrations\_signups

Event signup forms and their configuration.

| Column                   | Type          | Description                                  |
| ------------------------ | ------------- | -------------------------------------------- |
| `id`                     | UUID          | Parable's unique identifier                  |
| `signup_id`              | VARCHAR(64)   | Planning Center's signup ID                  |
| `name`                   | VARCHAR(255)  | Event name                                   |
| `description`            | TEXT          | Event description                            |
| `archived`               | BOOLEAN       | Whether the signup is archived               |
| `open_at`                | TIMESTAMP     | When registration opens                      |
| `close_at`               | TIMESTAMP     | When registration closes                     |
| `logo_url`               | VARCHAR(2048) | URL to event logo/image                      |
| `new_registration_url`   | VARCHAR(2048) | Direct link to registration form             |
| `created_at`             | TIMESTAMP     | When signup was created                      |
| `updated_at`             | TIMESTAMP     | Last update time                             |
| `tenant_organization_id` | INTEGER       | Organization identifier                      |
| `system_status`          | VARCHAR(50)   | Data sync status (active/transferring/stale) |
| `system_created_at`      | TIMESTAMP     | When record was created in Parable           |
| `system_updated_at`      | TIMESTAMP     | When record was last updated in Parable      |

### registrations\_attendees

Individual attendee records for events.

| Column                   | Type        | Description                             |
| ------------------------ | ----------- | --------------------------------------- |
| `id`                     | UUID        | Parable's unique identifier             |
| `attendee_id`            | VARCHAR(64) | Planning Center's attendee ID           |
| `active`                 | BOOLEAN     | Whether registration is active          |
| `canceled`               | BOOLEAN     | Whether registration was canceled       |
| `waitlisted`             | BOOLEAN     | Whether attendee is waitlisted          |
| `waitlisted_at`          | TIMESTAMP   | When added to waitlist                  |
| `created_at`             | TIMESTAMP   | When attendee record was created        |
| `updated_at`             | TIMESTAMP   | Last update time                        |
| `tenant_organization_id` | INTEGER     | Organization identifier                 |
| `system_status`          | VARCHAR(50) | Data sync status                        |
| `system_created_at`      | TIMESTAMP   | When record was created in Parable      |
| `system_updated_at`      | TIMESTAMP   | When record was last updated in Parable |

### registrations\_registrations

Registration submissions (minimal fields in current implementation).

| Column                   | Type        | Description                             |
| ------------------------ | ----------- | --------------------------------------- |
| `id`                     | UUID        | Parable's unique identifier             |
| `registration_id`        | VARCHAR(64) | Planning Center's registration ID       |
| `created_at`             | TIMESTAMP   | When registration was created           |
| `updated_at`             | TIMESTAMP   | Last update time                        |
| `tenant_organization_id` | INTEGER     | Organization identifier                 |
| `system_status`          | VARCHAR(50) | Data sync status                        |
| `system_created_at`      | TIMESTAMP   | When record was created in Parable      |
| `system_updated_at`      | TIMESTAMP   | When record was last updated in Parable |

### registrations\_categories

Event categories for grouping and filtering.

| Column                   | Type         | Description                             |
| ------------------------ | ------------ | --------------------------------------- |
| `id`                     | UUID         | Parable's unique identifier             |
| `category_id`            | VARCHAR(64)  | Planning Center's category ID           |
| `name`                   | VARCHAR(255) | Category name                           |
| `created_at`             | TIMESTAMP    | When category was created               |
| `updated_at`             | TIMESTAMP    | Last update time                        |
| `tenant_organization_id` | INTEGER      | Organization identifier                 |
| `system_status`          | VARCHAR(50)  | Data sync status                        |
| `system_created_at`      | TIMESTAMP    | When record was created in Parable      |
| `system_updated_at`      | TIMESTAMP    | When record was last updated in Parable |

### registrations\_selection\_types

Pricing tiers and registration options.

| Column                   | Type         | Description                                |
| ------------------------ | ------------ | ------------------------------------------ |
| `id`                     | UUID         | Parable's unique identifier                |
| `selection_type_id`      | VARCHAR(64)  | Planning Center's selection type ID        |
| `name`                   | VARCHAR(255) | Selection type name                        |
| `price_cents`            | INTEGER      | Price in cents (divide by 100 for dollars) |
| `publicly_available`     | BOOLEAN      | Whether available to public                |
| `created_at`             | TIMESTAMP    | When created                               |
| `updated_at`             | TIMESTAMP    | Last update time                           |
| `tenant_organization_id` | INTEGER      | Organization identifier                    |
| `system_status`          | VARCHAR(50)  | Data sync status                           |
| `system_created_at`      | TIMESTAMP    | When record was created in Parable         |
| `system_updated_at`      | TIMESTAMP    | When record was last updated in Parable    |

### registrations\_signup\_locations

Event venues with geographic coordinates.

| Column                   | Type             | Description                             |
| ------------------------ | ---------------- | --------------------------------------- |
| `id`                     | UUID             | Parable's unique identifier             |
| `signup_location_id`     | VARCHAR(64)      | Planning Center's location ID           |
| `name`                   | VARCHAR(255)     | Location name                           |
| `formatted_address`      | VARCHAR(512)     | Short formatted address                 |
| `full_formatted_address` | VARCHAR(512)     | Complete formatted address              |
| `latitude`               | DOUBLE PRECISION | Geographic latitude                     |
| `longitude`              | DOUBLE PRECISION | Geographic longitude                    |
| `location_type`          | VARCHAR(50)      | Type of location                        |
| `subpremise`             | VARCHAR(255)     | Room/unit number                        |
| `url`                    | VARCHAR(2048)    | URL for location info/maps              |
| `created_at`             | TIMESTAMP        | When created                            |
| `updated_at`             | TIMESTAMP        | Last update time                        |
| `tenant_organization_id` | INTEGER          | Organization identifier                 |
| `system_status`          | VARCHAR(50)      | Data sync status                        |
| `system_created_at`      | TIMESTAMP        | When record was created in Parable      |
| `system_updated_at`      | TIMESTAMP        | When record was last updated in Parable |

### registrations\_signup\_times

Event date and time slots.

| Column                   | Type        | Description                             |
| ------------------------ | ----------- | --------------------------------------- |
| `id`                     | UUID        | Parable's unique identifier             |
| `signup_time_id`         | VARCHAR(64) | Planning Center's time ID               |
| `starts_at`              | TIMESTAMP   | Event start time                        |
| `ends_at`                | TIMESTAMP   | Event end time                          |
| `all_day`                | BOOLEAN     | Whether this is an all-day event        |
| `created_at`             | TIMESTAMP   | When created                            |
| `updated_at`             | TIMESTAMP   | Last update time                        |
| `tenant_organization_id` | INTEGER     | Organization identifier                 |
| `system_status`          | VARCHAR(50) | Data sync status                        |
| `system_created_at`      | TIMESTAMP   | When record was created in Parable      |
| `system_updated_at`      | TIMESTAMP   | When record was last updated in Parable |

### registrations\_emergency\_contacts

Emergency contact information for attendees.

| Column                   | Type         | Description                             |
| ------------------------ | ------------ | --------------------------------------- |
| `id`                     | UUID         | Parable's unique identifier             |
| `emergency_contact_id`   | VARCHAR(64)  | Planning Center's contact ID            |
| `name`                   | VARCHAR(255) | Contact name                            |
| `phone_number`           | VARCHAR(255) | Contact phone number                    |
| `tenant_organization_id` | INTEGER      | Organization identifier                 |
| `system_status`          | VARCHAR(50)  | Data sync status                        |
| `system_created_at`      | TIMESTAMP    | When record was created in Parable      |
| `system_updated_at`      | TIMESTAMP    | When record was last updated in Parable |

### registrations\_people

Basic person information for registrations.

| Column                   | Type         | Description                             |
| ------------------------ | ------------ | --------------------------------------- |
| `id`                     | UUID         | Parable's unique identifier             |
| `person_id`              | VARCHAR(64)  | Planning Center's person ID             |
| `first_name`             | VARCHAR(255) | First name                              |
| `last_name`              | VARCHAR(255) | Last name                               |
| `name`                   | VARCHAR(255) | Full name                               |
| `tenant_organization_id` | INTEGER      | Organization identifier                 |
| `system_status`          | VARCHAR(50)  | Data sync status                        |
| `system_created_at`      | TIMESTAMP    | When record was created in Parable      |
| `system_updated_at`      | TIMESTAMP    | When record was last updated in Parable |

### registrations\_campuses

Church campus locations.

| Column                   | Type         | Description                             |
| ------------------------ | ------------ | --------------------------------------- |
| `id`                     | UUID         | Parable's unique identifier             |
| `campus_id`              | VARCHAR(64)  | Planning Center's campus ID             |
| `name`                   | VARCHAR(255) | Campus name                             |
| `created_at`             | TIMESTAMP    | When created                            |
| `updated_at`             | TIMESTAMP    | Last update time                        |
| `tenant_organization_id` | INTEGER      | Organization identifier                 |
| `system_status`          | VARCHAR(50)  | Data sync status                        |
| `system_created_at`      | TIMESTAMP    | When record was created in Parable      |
| `system_updated_at`      | TIMESTAMP    | When record was last updated in Parable |

### registrations\_organizations

Organization settings and configuration.

| Column                   | Type         | Description                             |
| ------------------------ | ------------ | --------------------------------------- |
| `id`                     | UUID         | Parable's unique identifier             |
| `organization_id`        | VARCHAR(64)  | Planning Center's organization ID       |
| `name`                   | VARCHAR(255) | Organization name                       |
| `created_at`             | TIMESTAMP    | When created                            |
| `updated_at`             | TIMESTAMP    | Last update time                        |
| `tenant_organization_id` | INTEGER      | Organization identifier                 |
| `system_status`          | VARCHAR(50)  | Data sync status                        |
| `system_created_at`      | TIMESTAMP    | When record was created in Parable      |
| `system_updated_at`      | TIMESTAMP    | When record was last updated in Parable |

## Relationship Tables

### registrations\_signup\_relationships

Links signups to related entities (categories, campuses, locations, times).

| Column                   | Type        | Description                                   |
| ------------------------ | ----------- | --------------------------------------------- |
| `id`                     | UUID        | Parable's unique identifier                   |
| `signup_id`              | VARCHAR(64) | Parent signup ID                              |
| `relationship_type`      | VARCHAR(50) | Type of relationship (category, campus, etc.) |
| `relationship_id`        | VARCHAR(64) | ID of related entity                          |
| `tenant_organization_id` | INTEGER     | Organization identifier                       |
| `system_status`          | VARCHAR(50) | Data sync status                              |
| `system_created_at`      | TIMESTAMP   | When record was created in Parable            |
| `system_updated_at`      | TIMESTAMP   | When record was last updated in Parable       |

**Relationship Types:**

* `category` - Links to registrations\_categories
* `campus` - Links to registrations\_campuses
* `signup_location` - Links to registrations\_signup\_locations
* `signup_time` - Links to registrations\_signup\_times

### registrations\_registration\_relationships

Links registrations to related entities.

| Column                   | Type        | Description                             |
| ------------------------ | ----------- | --------------------------------------- |
| `id`                     | UUID        | Parable's unique identifier             |
| `registration_id`        | VARCHAR(64) | Parent registration ID                  |
| `relationship_type`      | VARCHAR(50) | Type of relationship                    |
| `relationship_id`        | VARCHAR(64) | ID of related entity                    |
| `tenant_organization_id` | INTEGER     | Organization identifier                 |
| `system_status`          | VARCHAR(50) | Data sync status                        |
| `system_created_at`      | TIMESTAMP   | When record was created in Parable      |
| `system_updated_at`      | TIMESTAMP   | When record was last updated in Parable |

**Relationship Types:**

* `signup` - Links to registrations\_signups
* `person` - Links to registrations\_people

### registrations\_attendee\_relationships

Links attendees to related entities.

| Column                   | Type        | Description                             |
| ------------------------ | ----------- | --------------------------------------- |
| `id`                     | UUID        | Parable's unique identifier             |
| `attendee_id`            | VARCHAR(64) | Parent attendee ID                      |
| `relationship_type`      | VARCHAR(50) | Type of relationship                    |
| `relationship_id`        | VARCHAR(64) | ID of related entity                    |
| `tenant_organization_id` | INTEGER     | Organization identifier                 |
| `system_status`          | VARCHAR(50) | Data sync status                        |
| `system_created_at`      | TIMESTAMP   | When record was created in Parable      |
| `system_updated_at`      | TIMESTAMP   | When record was last updated in Parable |

**Relationship Types:**

* `signup` - Links to registrations\_signups
* `registration` - Links to registrations\_registrations
* `emergency_contact` - Links to registrations\_emergency\_contacts

## System Fields

All tables include these system fields for data management:

* **`system_status`** - Tracks data lifecycle:
  * `transferring` - Data being synced from Planning Center
  * `active` - Current, queryable data
  * `stale` - Outdated data pending removal

* **`tenant_organization_id`** - Ensures data isolation between organizations

* **`system_created_at`** - When Parable first received this record

* **`system_updated_at`** - Last sync timestamp

## Row Level Security

All tables implement Row Level Security (RLS) policies that:

1. Filter data to only show `active` records
2. Restrict access to the authenticated organization's data
3. Ensure complete data isolation between tenants

## Data Integrity Rules

1. **Schema Qualification**: Always use `planning_center.` prefix for all table references
2. **Row Level Security**: RLS automatically handles multi-tenancy and status filtering - do not add manual filters
3. **Monetary Values**: Cost and fee columns are stored in cents - divide by 100.0 for display
4. **Registration Status Flags**: Use booleans like `archived`, `canceled`, and `waitlisted` to control visibility instead of relying on `system_status`
5. **Direct ID Columns**: Core tables like `registrations_signups` expose direct ID columns for performance-critical joins

## Common Mistakes to Avoid

1. **Missing Schema Prefix**
   * ❌ `FROM registrations_signups`
   * ✅ `FROM planning_center.registrations_signups`

2. **Adding Redundant RLS Filters**
   * ❌ `WHERE tenant_organization_id = 1 AND system_status = 'active'`
   * ✅ Trust RLS to handle this automatically

3. **Joining Without Schema**
   * ❌ `JOIN registrations_attendees a ON ...`
   * ✅ `JOIN planning_center.registrations_attendees a ON ...`

4. **Skipping Currency Conversion**
   * ❌ `SELECT total_cost_cents as total_cost`
   * ✅ `SELECT total_cost_cents / 100.0 as total_cost`

## Performance Considerations

1. **Indexes**: All tables have optimized indexes on:
   * Primary keys and entity IDs
   * Join columns and foreign keys
   * Date columns for time-based queries

2. **Query Optimization**:
   * Always use the `planning_center.` schema prefix
   * RLS handles tenant and status filtering automatically
   * Filter registration status flags when relevant
   * Consider CTEs for complex aggregations
   * Use direct ID columns when available instead of relationship tables

## Best Practices

1. **Always join through relationship tables** - Relationship tables capture many-to-many links between events and related entities
2. **Trust RLS policies** - Skip manual `tenant_organization_id` or `system_status` filters
3. **Use Planning Center IDs for lookups** - The `*_id` fields (e.g., `signup_id`)
4. **Consider NULL values** - Many fields may be NULL if not provided by Planning Center
5. **Handle timestamps properly** - All timestamps are stored in UTC

## Example: Complete Event Details Query

```sql theme={null}
-- Get full event details with all related data
SELECT 
    s.signup_id,
    s.name as event_name,
    s.description,
    s.open_at,
    s.close_at,
    cat.name as category,
    camp.name as campus,
    loc.name as location_name,
    loc.full_formatted_address,
    tim.starts_at as event_start,
    tim.ends_at as event_end,
    tim.all_day
FROM planning_center.registrations_signups s
-- Join category
LEFT JOIN planning_center.registrations_signup_relationships sr_cat
    ON sr_cat.signup_id = s.signup_id 
    AND sr_cat.relationship_type = 'category'
LEFT JOIN planning_center.registrations_categories cat
    ON cat.category_id = sr_cat.relationship_id
-- Join campus
LEFT JOIN planning_center.registrations_signup_relationships sr_camp
    ON sr_camp.signup_id = s.signup_id 
    AND sr_camp.relationship_type = 'campus'
LEFT JOIN planning_center.registrations_campuses camp
    ON camp.campus_id = sr_camp.relationship_id
-- Join location
LEFT JOIN planning_center.registrations_signup_relationships sr_loc
    ON sr_loc.signup_id = s.signup_id 
    AND sr_loc.relationship_type = 'signup_location'
LEFT JOIN planning_center.registrations_signup_locations loc
    ON loc.signup_location_id = sr_loc.relationship_id
-- Join time
LEFT JOIN planning_center.registrations_signup_relationships sr_tim
    ON sr_tim.signup_id = s.signup_id 
    AND sr_tim.relationship_type = 'signup_time'
LEFT JOIN planning_center.registrations_signup_times tim
    ON tim.signup_time_id = sr_tim.relationship_id
WHERE s.archived = false
ORDER BY tim.starts_at DESC;
```

This query demonstrates how to properly join multiple related entities through the relationship tables to get complete event information.
