Skip to main content

Planning Center Publishing Data Model

Complete reference for all Planning Center Publishing tables in Parable: episodes, series, speakers, channels, and the relationships between them.

This document provides complete documentation of ALL tables in the Planning Center Publishing data model in Parable, including all entity tables and relationship tables with full field definitions.

Overview

The Publishing module manages your church's media content distribution, containing:

  • 13 entity tables - Episodes, series, channels, speakers, and supporting data
  • 4 relationship tables - Linking episodes, channels, series, and speakerships to related entities
  • Comprehensive metrics - View counts, downloads, and engagement tracking

Visual Data Model

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

Core Entity Relationships

Publishing module data model

Open diagram in new tab →

Key Relationships Explained

Content Hierarchy:

  1. CHANNEL is the top-level podcast/media feed
  2. SERIES organizes episodes by topic or theme
  3. EPISODE is the individual sermon, message, or content piece
  4. Hierarchy: Channel → Series → Episode

Publishing Schedule:

  • CHANNEL_DEFAULT_TIME defines recurring publish schedule
  • CHANNEL_NEXT_TIME overrides next publish date/time
  • EPISODE_TIME tracks when specific episodes were/will be published
  • Supports both recurring schedules and one-off publications

Media Resources:

  • EPISODE_RESOURCE stores multiple formats per episode
  • Kinds include: audio, video, PDF notes, etc.
  • Each resource has URL and file size tracking
  • Single episode can have audio, video, and supplementary files

Speaker Management:

  • SPEAKER defines individuals who present content
  • SPEAKERSHIP links episodes to speakers (many-to-many)
  • Single episode can have multiple speakers
  • Speakers can appear in multiple episodes/series

Analytics:

  • EPISODE_STATISTIC tracks engagement metrics
  • Metrics: library watch count, live watch count, time periods
  • Historical tracking with date ranges
  • Enables trend analysis and content performance review

Templates & Organization:

  • NOTE_TEMPLATE provides reusable sermon note formats
  • ORGANIZATION links to Planning Center organization settings

Generic Relationship Pattern:

  • Inter-entity links are stored in *_relationships tables
  • Each relationship table holds a parent entity ID, relationship_type, and relationship_id
  • Episode times, episode resources, and channel times belong to their parent via relationship tables

Query Requirements

Schema Prefix

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

✅ CORRECT: SELECT * FROM planning_center.publishing_episodes ❌ INCORRECT: SELECT * FROM publishing_episodes

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.

Complete Table Inventory

Core Content Tables

1. publishing_episodes

Individual sermons, messages, and content pieces.

ColumnTypeDescription
idUUIDUnique internal identifier
episode_idVARCHAR(64)Planning Center episode ID
titleTEXTEpisode title
descriptionTEXTEpisode description
published_live_atTIMESTAMPWhen episode went live
published_to_library_atTIMESTAMPWhen added to library
video_urlTEXTPrimary video URL
video_embed_codeTEXTPrimary video embed code
video_thumbnail_urlTEXTVideo thumbnail image
library_video_urlTEXTLibrary video URL
library_video_embed_codeTEXTLibrary video embed code
library_video_thumbnail_urlTEXTLibrary thumbnail
library_audio_urlTEXTLibrary audio URL
library_streaming_serviceVARCHAR(255)Streaming provider for library
sermon_audioJSONBAudio file metadata
artJSONBArtwork/images metadata
church_center_urlTEXTChurch Center app URL
stream_typeVARCHAR(255)Live/recorded/hybrid
streaming_serviceVARCHAR(255)Streaming platform
page_actionsJSONBAvailable page actions
needs_library_audio_or_video_urlBOOLEANMissing media flag
needs_notes_templateBOOLEANMissing notes template flag
needs_video_urlBOOLEANMissing video flag
services_plan_remote_identifierVARCHAR(64)Services app plan ID
services_service_type_remote_identifierVARCHAR(64)Service type ID
created_atTIMESTAMPCreation timestamp
updated_atTIMESTAMPLast update timestamp
tenant_organization_idINTEGEROrganization identifier
system_statusVARCHAR(50)Data lifecycle status
system_created_atTIMESTAMPSystem creation time
system_updated_atTIMESTAMPSystem update time

2. publishing_series

Sermon series and content collections.

ColumnTypeDescription
idUUIDUnique internal identifier
series_idVARCHAR(64)Planning Center series ID
titleVARCHAR(255)Series title
descriptionTEXTSeries description
artJSONBSeries artwork metadata
church_center_urlVARCHAR(255)Church Center URL
started_atTIMESTAMPSeries start date
ended_atTIMESTAMPSeries end date
episodes_countINTEGERNumber of episodes
publishedBOOLEANPublication status
created_atTIMESTAMPCreation timestamp
updated_atTIMESTAMPLast update timestamp
tenant_organization_idINTEGEROrganization identifier
system_statusVARCHAR(50)Data lifecycle status
system_created_atTIMESTAMPSystem creation time
system_updated_atTIMESTAMPSystem update time

3. publishing_channels

Distribution channels and platforms.

ColumnTypeDescription
idUUIDUnique internal identifier
channel_idVARCHAR(64)Planning Center channel ID
nameTEXTChannel name
descriptionTEXTChannel description
artJSONBChannel artwork metadata
podcast_artJSONBPodcast artwork metadata
podcast_feed_urlTEXTPodcast RSS feed URL
podcast_settingsJSONBPodcast settings
church_center_urlTEXTChurch Center URL
urlTEXTChannel URL
publishedBOOLEANPublication status
positionINTEGERDisplay position
enable_audioBOOLEANAudio enabled flag
enable_on_demand_videoBOOLEANOn-demand video enabled
enable_watch_liveBOOLEANLive watch enabled
general_chat_enabledBOOLEANChat enabled flag
group_chat_enabledBOOLEANGroup chat enabled
sermon_notes_enabledBOOLEANSermon notes enabled
can_enable_chatBOOLEANCan enable chat
default_video_durationINTEGERDefault video duration
default_video_embed_codeTEXTDefault video embed code
default_video_urlTEXTDefault video URL
activate_episode_minutes_beforeINTEGEREpisode activation lead time
services_service_type_remote_identifierVARCHAR(64)Services app reference
created_atTIMESTAMPCreation timestamp
updated_atTIMESTAMPLast update timestamp
tenant_organization_idINTEGEROrganization identifier
system_statusVARCHAR(50)Data lifecycle status
system_created_atTIMESTAMPSystem creation time
system_updated_atTIMESTAMPSystem update time

4. publishing_speakers

Speaker profiles and information.

ColumnTypeDescription
idUUIDUnique internal identifier
speaker_idVARCHAR(64)Planning Center speaker ID
first_nameVARCHAR(255)Speaker first name
last_nameVARCHAR(255)Speaker last name
formatted_nameVARCHAR(255)Full formatted name
name_prefixVARCHAR(50)Name prefix (Dr., Rev., etc.)
name_suffixVARCHAR(50)Name suffix
speaker_typeVARCHAR(50)Speaker type
avatar_urlVARCHAR(255)Speaker avatar/photo URL
episodes_countINTEGERNumber of episodes
tenant_organization_idINTEGEROrganization identifier
system_statusVARCHAR(50)Data lifecycle status
system_created_atTIMESTAMPSystem creation time
system_updated_atTIMESTAMPSystem update time

Relationship Tables

5. publishing_speakerships

Links episodes to speakers (junction table).

ColumnTypeDescription
idUUIDUnique internal identifier
speakership_idVARCHAR(64)Planning Center speakership ID (links to episodes via publishing_episodes_relationships with relationship_type='speakerships'; links to speakers via publishing_speakerships_relationships with relationship_type='speaker')
tenant_organization_idINTEGEROrganization identifier
system_statusVARCHAR(50)Data lifecycle status
system_created_atTIMESTAMPSystem creation time
system_updated_atTIMESTAMPSystem update time

Resource and Media Tables

6. publishing_episode_resources

Files and resources attached to episodes.

ColumnTypeDescription
idUUIDUnique internal identifier
episode_resource_idVARCHAR(64)Planning Center resource ID (links to episodes via publishing_episodes_relationships with relationship_type='episode_resources')
titleTEXTResource title
kindVARCHAR(255)Resource kind
typeVARCHAR(255)Resource type
iconTEXTResource icon
urlTEXTResource URL
featuredBOOLEANFeatured resource flag
positionINTEGERDisplay position
tenant_organization_idINTEGEROrganization identifier
system_statusVARCHAR(50)Data lifecycle status
system_created_atTIMESTAMPSystem creation time
system_updated_atTIMESTAMPSystem update time

7. publishing_note_templates

Templates for sermon notes and outlines.

ColumnTypeDescription
idUUIDUnique internal identifier
note_template_idVARCHAR(64)Planning Center template ID (links to episodes via publishing_episodes_relationships with relationship_type='note_template')
auto_create_free_form_notesBOOLEANWhether to auto-create free-form notes
enabledBOOLEANWhether template is enabled
published_atTIMESTAMPWhen template was published
templateTEXTTemplate content
tenant_organization_idINTEGEROrganization identifier
system_statusVARCHAR(50)Data lifecycle status
system_created_atTIMESTAMPSystem creation time
system_updated_atTIMESTAMPSystem update time

Scheduling Tables

8. publishing_episode_times

Publishing schedule for episodes on different channels.

ColumnTypeDescription
idUUIDUnique internal identifier
episode_time_idVARCHAR(64)Planning Center time ID (links to episodes via publishing_episodes_relationships with relationship_type='episode_times')
starts_atTIMESTAMPEpisode start time
ends_atTIMESTAMPEpisode end time
current_stateVARCHAR(50)Current publish state
streaming_serviceVARCHAR(50)Streaming service
video_urlTEXTEpisode video URL
video_embed_codeTEXTVideo embed code
caveatsJSONBPublishing caveats
timestamp_currentDOUBLE PRECISIONCurrent playback timestamp in seconds
tenant_organization_idINTEGEROrganization identifier
system_statusVARCHAR(50)Data lifecycle status
system_created_atTIMESTAMPSystem creation time
system_updated_atTIMESTAMPSystem update time

9. publishing_channel_default_times

Default publishing schedules per channel.

ColumnTypeDescription
idUUIDUnique internal identifier
channel_default_time_idVARCHAR(64)Planning Center default time ID (links to channels via publishing_channels_relationships with relationship_type='channel_default_times')
day_of_weekINTEGERDay (0=Sunday, 6=Saturday)
hourINTEGERPublish hour
minuteINTEGERPublish minute
frequencyVARCHAR(50)Recurrence frequency
positionINTEGERDisplay position
tenant_organization_idINTEGEROrganization identifier
system_statusVARCHAR(50)Data lifecycle status
system_created_atTIMESTAMPSystem creation time
system_updated_atTIMESTAMPSystem update time

10. publishing_channel_next_times

Upcoming scheduled publishes per channel.

ColumnTypeDescription
idUUIDUnique internal identifier
channel_next_time_idVARCHAR(64)Planning Center next time ID (links to channels via publishing_channels_relationships with relationship_type='next_times')
starts_atTIMESTAMPNext scheduled publish time
tenant_organization_idINTEGEROrganization identifier
system_statusVARCHAR(50)Data lifecycle status
system_created_atTIMESTAMPSystem creation time
system_updated_atTIMESTAMPSystem update time

Analytics Tables

11. publishing_episode_statistics

View counts, downloads, and engagement metrics.

ColumnTypeDescription
idUUIDUnique internal identifier
episode_statistics_idVARCHAR(64)Planning Center statistic ID — follows pattern `'es-'
titleVARCHAR(255)Episode title (snapshot)
library_watch_countINTEGERLibrary watch count
live_watch_countINTEGERLive watch count
published_live_atTIMESTAMPWhen episode went live
published_to_library_atTIMESTAMPWhen added to library
tenant_organization_idINTEGEROrganization identifier
system_statusVARCHAR(50)Data lifecycle status
system_created_atTIMESTAMPSystem creation time
system_updated_atTIMESTAMPSystem update time

12. publishing_episode_statistic_times

Statistics tracked over time periods.

ColumnTypeDescription
idUUIDUnique internal identifier
episode_statistics_idVARCHAR(64)Parent episode statistics ID (matches publishing_episode_statistics.episode_statistics_id)
time_idVARCHAR(64)Planning Center time ID
starts_atTIMESTAMPPeriod start time
watch_countINTEGERWatches in period
tenant_organization_idINTEGEROrganization identifier
system_statusVARCHAR(50)Data lifecycle status
system_created_atTIMESTAMPSystem creation time
system_updated_atTIMESTAMPSystem update time

Configuration Tables

13. publishing_organizations

Organization-level publishing settings.

ColumnTypeDescription
idUUIDUnique internal identifier
organization_idVARCHAR(64)Planning Center org ID
nameVARCHAR(255)Organization name
subdomainVARCHAR(255)Organization subdomain
downloads_usedINTEGERNumber of downloads used
tenant_organization_idINTEGEROrganization identifier
system_statusVARCHAR(50)Data lifecycle status
system_created_atTIMESTAMPSystem creation time
system_updated_atTIMESTAMPSystem update time

Relationship Tables

All relationship tables share this structure: a parent entity ID, relationship_type (VARCHAR(50)), and relationship_id (VARCHAR(64)) to identify the related record, plus standard system fields.

14. publishing_channels_relationships

Links channels to related entities (default times, next times, episodes).

ColumnTypeDescription
idUUIDUnique internal identifier
channel_idVARCHAR(64)Parent channel ID
relationship_typeVARCHAR(50)Type of relationship
relationship_idVARCHAR(64)ID of related entity
tenant_organization_idINTEGEROrganization identifier
system_statusVARCHAR(50)Data lifecycle status
system_created_atTIMESTAMPSystem creation time
system_updated_atTIMESTAMPSystem update time

Common relationship types:

  • channel_default_times - Links to publishing_channel_default_times
  • next_times - Links to publishing_channel_next_times

15. publishing_episodes_relationships

Links episodes to related entities (series, channels, resources, times, speakerships, note templates).

ColumnTypeDescription
idUUIDUnique internal identifier
episode_idVARCHAR(64)Parent episode ID
relationship_typeVARCHAR(50)Type of relationship
relationship_idVARCHAR(64)ID of related entity
tenant_organization_idINTEGEROrganization identifier
system_statusVARCHAR(50)Data lifecycle status
system_created_atTIMESTAMPSystem creation time
system_updated_atTIMESTAMPSystem update time

Common relationship types:

  • series - Links to publishing_series
  • channel - Links to publishing_channels
  • episode_resources - Links to publishing_episode_resources
  • episode_times - Links to publishing_episode_times
  • speakerships - Links to publishing_speakerships
  • note_template - Links to publishing_note_templates

16. publishing_series_relationships

Links series to related entities (channels, episodes).

ColumnTypeDescription
idUUIDUnique internal identifier
series_idVARCHAR(64)Parent series ID
relationship_typeVARCHAR(50)Type of relationship
relationship_idVARCHAR(64)ID of related entity
tenant_organization_idINTEGEROrganization identifier
system_statusVARCHAR(50)Data lifecycle status
system_created_atTIMESTAMPSystem creation time
system_updated_atTIMESTAMPSystem update time

17. publishing_speakerships_relationships

Links speakerships to related entities (speakers, episodes).

ColumnTypeDescription
idUUIDUnique internal identifier
speakership_idVARCHAR(64)Parent speakership ID
relationship_typeVARCHAR(50)Type of relationship
relationship_idVARCHAR(64)ID of related entity
tenant_organization_idINTEGEROrganization identifier
system_statusVARCHAR(50)Data lifecycle status
system_created_atTIMESTAMPSystem creation time
system_updated_atTIMESTAMPSystem update time

Common relationship types:

  • speaker - Links to publishing_speakers
  • episode - Links to publishing_episodes

System Fields

All tables include these system fields for data management:

  • tenant_organization_id - Multi-tenant organization identifier
  • system_status - Data lifecycle status (active, transferring, stale)
  • system_created_at - When the record was created in Parable
  • system_updated_at - When the record was last updated in Parable

Row Level Security

All tables implement Row Level Security (RLS) to ensure tenant isolation:

-- Example RLS policy
CREATE POLICY tenant_read_only ON planning_center.publishing_episodes
  FOR SELECT
  TO PUBLIC
  USING (
    system_status = 'active'
    AND EXISTS (
      SELECT 1 FROM public.tenant_dsn_credentials dsn
      WHERE dsn.role_name = CURRENT_ROLE
        AND dsn.tenant_organization_id = planning_center.publishing_episodes.tenant_organization_id
    )
  );

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: Any monetization or purchase amount columns are stored in cents - divide by 100.0 for display
  4. Media Flags: Use booleans like needs_video_url and needs_library_audio_or_video_url to identify missing assets instead of relying on system_status
  5. Relationship Tables: All inter-entity links are stored in *_relationships tables — use publishing_episodes_relationships, publishing_channels_relationships, etc. for joins

Common Mistakes to Avoid

  1. Missing Schema Prefix

    • ❌ FROM publishing_episodes
    • ✅ FROM planning_center.publishing_episodes
  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 publishing_series s ON ...
    • ✅ JOIN planning_center.publishing_series s ON ...
  4. Skipping Currency Conversion

    • ❌ SELECT purchase_price_cents as purchase_price
    • ✅ SELECT purchase_price_cents / 100.0 as purchase_price

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 by publication state or media availability when relevant
    • Consider CTEs for aggregating view/download metrics
    • Use relationship tables for all cross-entity joins

Data Synchronization

Publishing data is synchronized through Temporal workflows:

  1. Master Workflow - Orchestrates all child workflows
  2. Independent Entities - Channels, Series, Speakers, Organizations
  3. Dependent Entities - Episodes (depends on channels)
  4. Related Data - Resources, times, statistics (depends on episodes)
  5. Junction Tables - Speakerships linking episodes to speakers

Usage Tips

  1. Trust RLS for active data - Skip manual system_status or tenant filters
  2. Join through relationship tables - Use publishing_episodes_relationships, publishing_channels_relationships, etc.
  3. Consider NULL values - Many fields are optional
  4. Use JSONB operators for nested data in art, sermon_audio, page_actions fields
  5. Aggregate statistics over time periods for trends

Common Join Patterns

Episodes with Series and Speakers

SELECT 
    e.title as episode_title,
    s.title as series_title,
    sp.formatted_name as speaker_name
FROM planning_center.publishing_episodes e
LEFT JOIN planning_center.publishing_episodes_relationships er_series
    ON er_series.episode_id = e.episode_id AND er_series.relationship_type = 'series'
LEFT JOIN planning_center.publishing_series s ON s.series_id = er_series.relationship_id
LEFT JOIN planning_center.publishing_episodes_relationships er_ship
    ON er_ship.episode_id = e.episode_id AND er_ship.relationship_type = 'speakerships'
LEFT JOIN planning_center.publishing_speakerships_relationships spr
    ON spr.speakership_id = er_ship.relationship_id AND spr.relationship_type = 'speaker'
LEFT JOIN planning_center.publishing_speakers sp ON sp.speaker_id = spr.relationship_id;

Episodes with Statistics and Resources

SELECT 
    e.title,
    est.library_watch_count,
    est.live_watch_count,
    er.title as resource_title,
    er.url as resource_url
FROM planning_center.publishing_episodes e
LEFT JOIN planning_center.publishing_episode_statistics est 
    ON est.episode_statistics_id = 'es-' || e.episode_id
LEFT JOIN planning_center.publishing_episodes_relationships er_res
    ON er_res.episode_id = e.episode_id AND er_res.relationship_type = 'episode_resources'
LEFT JOIN planning_center.publishing_episode_resources er ON er.episode_resource_id = er_res.relationship_id;

Data Quality Notes

  • Episode published_live_at indicates published content
  • Series may have NULL ended_at for ongoing series
  • Statistics are point-in-time snapshots (episode_statistics_id = 'es-' || episode_id)
  • Speakerships link episodes to speakers via publishing_episodes_relationships and publishing_speakerships_relationships
  • Episodes link to channels, series, and resources via publishing_episodes_relationships

This data model enables comprehensive media analytics and content management for your church's publishing ministry.

On this page