REST API
This document describes all REST API endpoints available in Rondo Club, including both WordPress standard endpoints and custom endpoints.
Authentication
Section titled “Authentication”All API requests require authentication via WordPress session with REST nonce.
Headers:
X-WP-Nonce: {nonce_value}The nonce is automatically injected by the frontend via window.wpApiSettings.nonce.
API Namespaces
Section titled “API Namespaces”Rondo Club uses two API namespaces:
| Namespace | Purpose |
|---|---|
/wp/v2/ | Standard WordPress REST API for CRUD operations on post types |
/rondo/v1/ | Custom endpoints for dashboard, search, and specialized operations |
Standard WordPress Endpoints (/wp/v2/)
Section titled “Standard WordPress Endpoints (/wp/v2/)”These endpoints are provided by WordPress with access control applied:
People
Section titled “People”| Method | Endpoint | Description |
|---|---|---|
| GET | /wp/v2/people | List all accessible people |
| GET | /wp/v2/people/{id} | Get single person |
| POST | /wp/v2/people | Create new person |
| PUT | /wp/v2/people/{id} | Update person |
| DELETE | /wp/v2/people/{id} | Delete person |
| Method | Endpoint | Description |
|---|---|---|
| GET | /wp/v2/teams | List all accessible teams |
| GET | /wp/v2/teams/{id} | Get single team |
| POST | /wp/v2/teams | Create new team |
| PUT | /wp/v2/teams/{id} | Update team |
| DELETE | /wp/v2/teams/{id} | Delete team |
Taxonomies
Section titled “Taxonomies”| Method | Endpoint | Description |
|---|---|---|
| GET | /wp/v2/relationship_type | List relationship types |
| GET | /wp/v2/seizoen | List seasons (for discipline cases) |
Custom Endpoints (/rondo/v1/)
Section titled “Custom Endpoints (/rondo/v1/)”These endpoints provide specialized functionality beyond basic CRUD operations.
Dashboard
Section titled “Dashboard”GET /rondo/v1/dashboard
Returns summary statistics and recent activity for the dashboard.
Permission: Logged in users only
Response:
{ "stats": { "total_people": 150, "total_teams": 45 }, "recent_people": [ { "id": 123, "name": "John Doe", "first_name": "John", "infix": "", "last_name": "Doe", "thumbnail": "https://...", "is_favorite": true } ], "upcoming_reminders": [ { "id": 456, "title": "John Doe's Birthday", "date_value": "2025-01-15", "days_until": 5, "is_recurring": true } ], "favorites": [...]}Version
Section titled “Version”GET /rondo/v1/version
Returns the current theme version. Used for PWA/mobile app cache invalidation.
Permission: Public (no authentication required)
Response:
{ "version": "1.42.0"}This endpoint is called periodically by the frontend to detect when a new version has been deployed, allowing users to reload and get the latest code.
Global Search
Section titled “Global Search”GET /rondo/v1/search
Search across people and teams.
Permission: Logged in users only
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
q | string | Yes | Search query (minimum 2 characters) |
Response:
{ "people": [ { "id": 1, "name": "John Doe", "thumbnail": "...", "is_favorite": true } ], "teams": [ { "id": 2, "name": "Acme Corp", "thumbnail": "...", "website": "https://..." } ]}Upcoming Reminders
Section titled “Upcoming Reminders”GET /rondo/v1/reminders
Get upcoming birthdays for reminders.
Permission: Logged in users only
Parameters:
| Name | Type | Default | Description |
|---|---|---|---|
days_ahead | int | 30 | Number of days to look ahead (1-365) |
Response:
[ { "id": 123, "title": "John's Birthday", "next_occurrence": "2025-01-20", "days_until": 10, "related_people": [ { "id": 456, "name": "John Doe", "thumbnail": "..." } ] }]Birthdays are generated from the birthdate field on person records.
People by Team
Section titled “People by Team”GET /rondo/v1/teams/{team_id}/people
Get all people who work or worked at a team.
Permission: Must have access to the team
Response:
{ "current": [ { "id": 1, "name": "John Doe", "thumbnail": "...", "job_title": "CEO", "start_date": "2020-01-15", "end_date": "" } ], "former": [ { "id": 2, "name": "Jane Smith", "thumbnail": "...", "job_title": "CTO", "start_date": "2018-03-01", "end_date": "2023-06-30" } ]}People Filter Options
Section titled “People Filter Options”GET /rondo/v1/people/filter-options
Returns available filter options for the People list with counts. Options are derived dynamically from database values.
Authentication: Required (authenticated user)
Response:
{ "total": 523, "age_groups": [ { "value": "Onder 6", "count": 12 }, { "value": "Onder 7", "count": 18 }, { "value": "Onder 8", "count": 24 }, { "value": "Onder 9", "count": 31 }, { "value": "Onder 9 Meiden", "count": 15 }, { "value": "Onder 10", "count": 28 }, { "value": "Onder 11", "count": 35 }, { "value": "Onder 11 Meiden", "count": 18 }, { "value": "Onder 12", "count": 42 }, { "value": "Onder 13", "count": 38 }, { "value": "Onder 13 Meiden", "count": 19 }, { "value": "Onder 14", "count": 45 }, { "value": "Onder 15", "count": 41 }, { "value": "Onder 15 Meiden", "count": 22 }, { "value": "Onder 16", "count": 39 }, { "value": "Onder 17", "count": 36 }, { "value": "Onder 17 Meiden", "count": 20 }, { "value": "Onder 18", "count": 33 }, { "value": "Onder 19", "count": 29 }, { "value": "Senioren", "count": 87 }, { "value": "Senioren Vrouwen", "count": 34 } ], "member_types": [ { "value": "Junior", "count": 142 }, { "value": "Senior", "count": 287 }, { "value": "Donateur", "count": 51 }, { "value": "Lid van Verdienste", "count": 8 } ]}Notes:
- Only values with at least 1 matching person are included
- Age groups sorted youngest to oldest (numeric extraction from “Onder X”), gender variants after base groups
- Member types sorted in priority order (new types from sync appear at end)
- Frontend caches with 5-minute staleTime
Current User
Section titled “Current User”GET /rondo/v1/user/me
Get information about the currently logged in user.
Permission: Logged in users only
Response:
{ "id": 1, "name": "Admin User", "avatar_url": "https://...", "is_admin": true, "profile_url": "https://.../wp-admin/profile.php", "admin_url": "https://.../wp-admin/"}Person Photo Upload
Section titled “Person Photo Upload”POST /rondo/v1/people/{person_id}/photo
Upload and set a person’s profile photo. The filename is automatically generated from the person’s name.
Permission: Must be able to edit the person
Content-Type: multipart/form-data
Body:
file- Image file (JPEG, PNG, GIF, WebP)
Response:
{ "success": true, "attachment_id": 789, "filename": "john-doe.jpg", "thumbnail_url": "https://...", "full_url": "https://..."}Team Logo Upload
Section titled “Team Logo Upload”POST /rondo/v1/teams/{team_id}/logo/upload
Upload and set a team’s logo. The filename is automatically generated from the team name.
Permission: Must be able to edit the team
Content-Type: multipart/form-data
Body:
file- Image file (JPEG, PNG, GIF, WebP, SVG)
Response:
{ "success": true, "attachment_id": 789, "filename": "acme-corp-logo.png", "thumbnail_url": "https://...", "full_url": "https://..."}Set Team Logo (by Media ID)
Section titled “Set Team Logo (by Media ID)”POST /rondo/v1/teams/{team_id}/logo
Set a team’s logo from an existing media library item.
Permission: Must be able to edit the team
Body:
{ "media_id": 789}Response:
{ "success": true, "media_id": 789, "thumbnail_url": "https://...", "full_url": "https://..."}Restore Relationship Type Defaults
Section titled “Restore Relationship Type Defaults”POST /rondo/v1/relationship-types/restore-defaults
Restore default inverse relationship mappings and gender-dependent configurations.
Permission: Logged in users only
Response:
{ "success": true, "message": "Default relationship type configurations have been restored."}Workspaces
Section titled “Workspaces”GET /rondo/v1/workspaces
List all workspaces the current user is a member of.
Permission: Logged in users only
Response:
[ { "id": 1, "name": "My Workspace", "description": "Shared team workspace", "member_count": 3, "role": "owner" }]GET /rondo/v1/workspaces/{id}
Get single workspace with members.
Permission: Must be workspace member
Response:
{ "id": 1, "name": "My Workspace", "description": "Shared team workspace", "members": [ { "user_id": 1, "display_name": "John Doe", "role": "owner" } ]}POST /rondo/v1/workspaces
Create a new workspace.
Permission: Logged in users only
Body:
{ "name": "New Workspace", "description": "Optional description"}PUT /rondo/v1/workspaces/{id}
Update workspace details.
Permission: Must be workspace owner or admin
Body:
{ "name": "Updated Name", "description": "Updated description"}DELETE /rondo/v1/workspaces/{id}
Delete a workspace.
Permission: Must be workspace owner
Workspace Members
Section titled “Workspace Members”POST /rondo/v1/workspaces/{id}/members
Add a member to the workspace.
Permission: Must be workspace owner or admin
Body:
{ "user_id": 123, "role": "member"}PUT /rondo/v1/workspaces/{id}/members/{user_id}
Update member role.
Permission: Must be workspace owner or admin
Body:
{ "role": "admin"}DELETE /rondo/v1/workspaces/{id}/members/{user_id}
Remove a member from the workspace.
Permission: Must be workspace owner or admin
Workspace Invites
Section titled “Workspace Invites”GET /rondo/v1/workspaces/{id}/invites
List pending invites for a workspace.
Permission: Must be workspace owner or admin
POST /rondo/v1/workspaces/{id}/invites
Create and send an email invitation.
Permission: Must be workspace owner or admin
Body:
{ "role": "member"}DELETE /rondo/v1/workspaces/{id}/invites/{invite_id}
Revoke a pending invite.
Permission: Must be workspace owner or admin
GET /rondo/v1/invites/{token}
Validate an invite token (public endpoint).
Permission: Public (no authentication required)
Response:
{ "valid": true, "workspace_name": "Team Workspace", "invited_by": "John Doe", "role": "member"}POST /rondo/v1/invites/{token}/accept
Accept an invite and join the workspace.
Permission: Must be logged in
Direct Sharing (People)
Section titled “Direct Sharing (People)”GET /rondo/v1/people/{id}/shares
Get list of users a person is shared with.
Permission: Must be post owner
Response:
[ { "user_id": 123, "display_name": "Jane Smith", "avatar_url": "https://...", "permission": "view" }]POST /rondo/v1/people/{id}/shares
Share a person with another user.
Permission: Must be post owner
Body:
{ "user_id": 123, "permission": "view"}Response:
{ "success": true, "message": "Shared successfully."}DELETE /rondo/v1/people/{id}/shares/{user_id}
Remove sharing from a user.
Permission: Must be post owner
Response:
{ "success": true, "message": "Share removed."}Direct Sharing (Teams)
Section titled “Direct Sharing (Teams)”GET /rondo/v1/teams/{id}/shares
Get list of users a team is shared with.
Permission: Must be post owner
Response: Same format as People shares.
POST /rondo/v1/teams/{id}/shares
Share a team with another user.
Permission: Must be post owner
Body: Same format as People shares.
DELETE /rondo/v1/teams/{id}/shares/{user_id}
Remove sharing from a user.
Permission: Must be post owner
User Search
Section titled “User Search”GET /rondo/v1/users/search
Search for users to share with.
Permission: Logged in users only
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
q | string | Yes | Search query (minimum 2 characters) |
Response:
[ { "id": 123, "display_name": "Jane Smith", "avatar_url": "https://..." }]Note: The current user is automatically excluded from search results.
Mention Notifications Preference
Section titled “Mention Notifications Preference”POST /rondo/v1/user/mention-notifications
Update the user’s preference for @mention notifications.
Permission: Logged in users only
Body:
{ "preference": "digest"}Valid values:
digest- Include mentions in daily digest (default)immediate- Send email notification immediately when mentionednever- Do not notify me of mentions
Response:
{ "success": true, "mention_notifications": "digest"}The preference is also returned by GET /rondo/v1/user/notification-channels as part of the response:
{ "channels": ["email"], "notification_time": "09:00", "mention_notifications": "digest"}Workspace Member Search
Section titled “Workspace Member Search”GET /rondo/v1/workspaces/members/search
Search for workspace members for @mention autocomplete.
Permission: Logged in users only
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
workspace_ids | string | Yes | Comma-separated workspace IDs |
query | string | Yes | Search query for member names |
Response:
[ { "id": 123, "name": "Jane Smith", }]Response Enhancements
Section titled “Response Enhancements”Person Relationships Expansion
Section titled “Person Relationships Expansion”The rest_prepare_person filter automatically expands relationship data in person responses:
{ "acf": { "relationships": [ { "related_person": 123, "person_name": "Jane Doe", "person_thumbnail": "https://...", "relationship_type": 5, "relationship_name": "Spouse", "relationship_slug": "spouse", "relationship_label": "" } ] }}ACF Fields on Relationship Types
Section titled “ACF Fields on Relationship Types”Relationship type taxonomy terms include ACF fields in their REST response:
{ "id": 5, "name": "Parent", "slug": "parent", "acf": { "inverse_relationship_type": 6, "is_gender_dependent": false, "gender_dependent_group": "" }}Error Responses
Section titled “Error Responses”All endpoints return standard WordPress REST error format:
{ "code": "rest_forbidden", "message": "You do not have permission to access this item.", "data": { "status": 403 }}Common error codes:
| Code | Status | Description |
|---|---|---|
rest_forbidden | 403 | Access denied |
rest_not_found | 404 | Resource not found |
rest_invalid_param | 400 | Invalid parameter |
not_logged_in | 401 | Authentication required |
Functie-Capability Map (Admin Only)
Section titled “Functie-Capability Map (Admin Only)”Manage the mapping between Sportlink “functies” (club-level roles) and Rondo permission roles.
GET /rondo/v1/functie-capability-map
Returns the current functie-to-role mapping.
Permission: Admin only
Response:
{ "map": { "Voorzitter": ["admin"], "Penningmeester": ["financieel"], "Secretaris": ["admin"], "Wedstrijdsecretaris": ["wedstrijdzaken"] }}POST /rondo/v1/functie-capability-map
Update the functie-to-role mapping.
Permission: Admin only
Body:
{ "map": { "Voorzitter": ["admin"], "Penningmeester": ["financieel"] }}Response:
{ "success": true, "map": { ... }}User Provisioning (Admin Only)
Section titled “User Provisioning (Admin Only)”Create WordPress user accounts from person records and manage provisioning settings.
POST /rondo/v1/people/{person_id}/provision
Provision a WordPress user account for a person. Creates a user with the Rondo User role, links it bidirectionally to the person record, and optionally sends a welcome email.
Permission: Admin only
Response:
{ "success": true, "user_id": 42, "person_id": 789, "welcome_email_sent": true}GET /rondo/v1/provisioning/settings
Returns current provisioning settings including the welcome email template.
Permission: Admin only
Response:
{ "welcome_email_subject": "Welkom bij Rondo", "welcome_email_body": "Beste {{naam}},\n\nJe account is aangemaakt...", "auto_send_welcome_email": true}POST /rondo/v1/provisioning/settings
Update provisioning settings.
Permission: Admin only
Body:
{ "welcome_email_subject": "Welkom bij Rondo", "welcome_email_body": "Beste {{naam}},\n\nJe account is aangemaakt...", "auto_send_welcome_email": true}Volunteer Role Classification (Admin Only)
Section titled “Volunteer Role Classification (Admin Only)”Manage how Sportlink job titles are classified for volunteer status calculation.
GET /rondo/v1/volunteer-roles/available
Returns all distinct job_title values from work_history across all person posts.
Permission: Admin only
Response: Array of strings (role names), sorted alphabetically.
GET /rondo/v1/volunteer-roles/settings
Returns current and default role classification arrays.
Permission: All authenticated users (read access for team detail page player/staff split)
Response:
{ "player_roles": ["Aanvaller", "Keeper", ...], "excluded_roles": ["Donateur", "Erelid", ...], "default_player_roles": ["Aanvaller", "Keeper", ...], "default_excluded_roles": ["Donateur", "Erelid", ...]}POST /rondo/v1/volunteer-roles/settings
Update role classifications. Triggers volunteer status recalculation for all people.
Permission: Admin only
Parameters:
| Name | Type | Description |
|---|---|---|
player_roles | array | Role names classified as player (not volunteer) |
excluded_roles | array | Role names excluded from volunteer count entirely |
Response:
{ "player_roles": ["Aanvaller", ...], "excluded_roles": ["Donateur", ...], "people_recalculated": 245}WordPress Options:
rondo_player_roles- Array of player role namesrondo_excluded_roles- Array of excluded role names
When no option is set, hardcoded defaults from VolunteerStatus class are used.
Related Documentation
Section titled “Related Documentation”- Access Control - How permissions work
- User Provisioning - Provisioning user accounts
- Data Model - Post types and fields
- VOG Filtered People - VOG tab endpoint with KNVB IDs and volunteer filters