{"id":39824208,"url":"https://github.com/extra-chill/extrachill-api","last_synced_at":"2026-05-18T02:19:05.257Z","repository":{"id":327848200,"uuid":"1107237692","full_name":"Extra-Chill/extrachill-api","owner":"Extra-Chill","description":"Central REST API infrastructure for the Extra Chill network. Enables headless use of the platform.","archived":false,"fork":false,"pushed_at":"2026-04-18T14:53:48.000Z","size":815,"stargazers_count":0,"open_issues_count":6,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-18T16:34:00.444Z","etag":null,"topics":["multisite","php","rest-api","wordpress"],"latest_commit_sha":null,"homepage":"https://extrachill.com","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Extra-Chill.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-30T20:46:21.000Z","updated_at":"2026-04-18T14:53:53.000Z","dependencies_parsed_at":"2026-04-26T21:00:43.066Z","dependency_job_id":null,"html_url":"https://github.com/Extra-Chill/extrachill-api","commit_stats":null,"previous_names":["extra-chill/extrachill-api"],"tags_count":29,"template":false,"template_full_name":null,"purl":"pkg:github/Extra-Chill/extrachill-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Extra-Chill%2Fextrachill-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Extra-Chill%2Fextrachill-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Extra-Chill%2Fextrachill-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Extra-Chill%2Fextrachill-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Extra-Chill","download_url":"https://codeload.github.com/Extra-Chill/extrachill-api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Extra-Chill%2Fextrachill-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32312505,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T19:15:34.056Z","status":"ssl_error","status_checked_at":"2026-04-26T19:15:15.467Z","response_time":129,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["multisite","php","rest-api","wordpress"],"created_at":"2026-01-18T13:02:50.856Z","updated_at":"2026-04-26T21:01:08.350Z","avatar_url":"https://github.com/Extra-Chill.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ExtraChill API\n\nNetwork-activated REST API infrastructure for the Extra Chill Platform WordPress multisite network. Centralizes all custom REST endpoints under a single `extrachill/v1` namespace for consistent access across web, mobile, and AI clients.\n\n## Overview\n\nThe ExtraChill API plugin provides a centralized, versioned REST API infrastructure that replaces legacy admin-ajax.php handlers with modern WordPress REST API endpoints. It uses automatic route discovery to modularly organize endpoints by feature area while maintaining a consistent API surface across the entire multisite network.\n\nThe plugin also owns the network-wide activity storage table (`{base_prefix}extrachill_activity`) used by the activity feed endpoints.\n\n## Features\n\n- **Network-Wide Activation**: All endpoints available on every site in the multisite network\n- **Activity Storage**: Maintains the network-wide `{base_prefix}extrachill_activity` table used by the activity feed endpoints\n- **Automatic Route Discovery**: Recursively loads route files from `inc/routes/`\n- **Versioned Namespace**: All endpoints are under `extrachill/v1`\n- **Modular Organization**: Routes are organized by feature (`admin/`, `artists/`, `shop/`, etc.)\n- **Security**: Endpoints use permission callbacks, validation, and sanitization (per-route implementation)\n- **Activity Storage**: Maintains a network-wide `{base_prefix}extrachill_activity` table used by activity endpoints\n\n## Current Endpoints\n\nThe plugin ships route files under `inc/routes/` (loaded recursively) and registers endpoints under the `extrachill/v1` namespace:\n\n### Authentication Endpoints (7)\n- `POST /auth/browser-handoff` - Browser handoff for cross-device auth\n- `POST /auth/google` - Google OAuth authentication\n- `POST /auth/login` - User login returning access + refresh tokens\n- `POST /auth/logout` - Logout and token revocation\n- `GET /auth/me` - Get current authenticated user\n- `POST /auth/refresh` - Refresh access tokens\n- `POST /auth/register` - User registration\n\n### Configuration Endpoints (1)\n- `GET /config/oauth` - OAuth provider configuration\n\n### Analytics Endpoints\n- `POST /analytics/view` - Async view tracking (increments `ec_post_views`)\n- `POST /analytics/click` - Unified click tracking\n- `GET /analytics/link-page` - Fetch link page analytics\n- `GET /analytics/events` - Query network analytics events (requires `manage_network_options`)\n- `GET /analytics/events/summary` - Aggregate network event stats (requires `manage_network_options`)\n- `GET /analytics/meta` - Analytics filter metadata (requires `manage_network_options`)\n- `POST /analytics/link-page` - Track link page view events\n\n### Artist API (9)\n- `GET/PUT /artists/{id}` - Core artist profile data\n- `GET/PUT /artists/{id}/socials` - Social media links\n- `GET/PUT /artists/{id}/links` - Link page data\n- `GET /artists/{id}/analytics` - Link page analytics\n- `GET /artists/{id}/permissions` - Check artist permissions\n- `GET/POST/DELETE /artists/{id}/roster` - Roster member management\n- `GET /artists/{id}/subscribers` - List subscribers with pagination\n- `GET /artists/{id}/subscribers/export` - Export subscribers as CSV\n- `POST /artists/{id}/subscribe` - Public subscription signup\n\n### Block Generators (3)\n- `POST /blog/band-name` - AI band name generation\n- `POST /blog/rapper-name` - AI rapper name generation\n- `POST /blog/ai-adventure` - AI adventure story generation\n\n### Image Voting (2)\n- `GET /blog/image-voting/vote-count/{post_id}/{instance_id}` - Get vote counts\n- `POST /blog/image-voting/vote` - Cast a vote\n\n### Community Endpoints (3)\n- `GET /users/search` - Search users for @mentions and admin\n- `POST /community/upvote` - Upvote topics or replies (authenticated)\n- `GET/POST/DELETE /community/drafts` - Manage bbPress drafts (authenticated)\n\n### Contact (1)\n- `POST /contact/submit` - Submit contact form with Turnstile verification\n\n### Activity Endpoints (2)\n- `GET /activity` - Activity feed with filtering and pagination (authenticated)\n- `GET /object` - Object resolver for posts, comments, and artists (authenticated)\n\n### Admin Endpoints (14)\n- `GET /admin/artist-access` - List pending artist access requests\n- `GET/POST /admin/artist-access/{user_id}/approve` - Approve artist access request\n- `POST /admin/artist-access/{user_id}/reject` - Reject artist access request\n- `GET /admin/lifetime-membership` - List all lifetime memberships\n- `POST /admin/lifetime-membership/grant` - Grant Lifetime Extra Chill Membership (ad-free)\n- `DELETE /admin/lifetime-membership/{user_id}` - Revoke Lifetime Extra Chill Membership\n- `GET /admin/team-members` - List all team members with search/pagination\n- `POST /admin/team-members/sync` - Sync team members\n- `PUT /admin/team-members/{user_id}` - Manage team member status\n- `POST /admin/taxonomies/sync` - Sync shared taxonomies across sites\n- `GET /admin/tag-migration` - List tags for migration searching\n- `GET /admin/forum-topics` - List and manage bbPress topics across network\n- `GET /admin/forum-topics/{topic_id}` - Manage a single bbPress topic\n- `PUT /admin/forum-topics/{topic_id}/status` - Update bbPress topic status\n- `GET /admin/404-logger` - Monitor 404 errors for SEO management\n- `GET /admin/artist-relationships` - Manage user-artist links\n\n### User Management (5)\n- `GET /users/{id}` - Get user profile\n- `GET/POST /users/onboarding` - User onboarding flow\n- `GET /users/leaderboard` - Get user leaderboard with rankings\n- `GET/POST/DELETE /users/{id}/artists` - Manage user-artist relationships\n- `GET /users/search` - Find users (multiple contexts)\n\n### Documentation (2)\n- `GET /docs-info` - Documentation metadata\n- `POST /sync/doc` - Sync documentation\n\n### Event Submissions (1)\n- `POST /event-submissions` - Submit event with optional flyer\n\n### Media Management (1)\n- `POST /media` - Upload media\n\n### Newsletter (2)\n- `POST /newsletter/subscribe` - Subscribe to newsletter\n- `POST /newsletter/campaign/push` - Push newsletter to Sendy\n\n### Shop Integration\n- `GET/POST/PUT/DELETE /shop/products` - Product CRUD operations\n- `GET /shop/orders` - List orders (requires WooCommerce on the shop site)\n- `PUT /shop/orders/{id}/status` - Mark shipped (`status=completed`)\n- `POST /shop/orders/{id}/refund` - Issue full refund\n- `POST/DELETE /shop/products/{id}/images` - Product image management\n- `GET/POST/DELETE /shop/stripe` - Stripe Connect management\n- `POST /shop/stripe-webhook` - Stripe webhook handler\n- `GET/PUT /shop/shipping-address` - Artist shipping from-address management\n- `GET/POST /shop/shipping-labels` - Purchase and retrieve shipping labels\n\n### Stream (1)\n- `GET /stream/status` - Check streaming status and configuration\n\n### Tools (2)\n- `POST /tools/qr-code` - Generate QR codes\n- `GET /tools/markdown-export` - Export content as markdown\n\n### SEO Endpoints (5)\n- `POST /seo/audit` - Start multisite SEO audit (full or batch mode)\n- `POST /seo/audit/continue` - Continue paused batch audit\n- `GET /seo/audit/status` - Check audit status and results\n- `GET /seo/audit/details` - Get detailed audit results by category with pagination\n- `GET /seo/config` - Get SEO audit configuration\n\n\nSee [CLAUDE.md](CLAUDE.md) for architectural patterns and [docs/routes/](docs/routes/) for complete endpoint documentation.\n\n## Usage\n\n### For Plugin Developers\n\nAdd new endpoints by creating route files in `inc/routes/`:\n\n```php\n\u003c?php\n/**\n * Custom endpoint registration\n */\n\nadd_action('extrachill_api_register_routes', function() {\n    register_rest_route('extrachill/v1', '/my-endpoint', [\n        'methods' =\u003e 'GET',\n        'callback' =\u003e 'my_endpoint_callback',\n        'permission_callback' =\u003e '__return_true',\n    ]);\n});\n\nfunction my_endpoint_callback($request) {\n    return rest_ensure_response(['status' =\u003e 'success']);\n}\n```\n\n### For Client Developers\n\nAccess endpoints using standard WordPress REST API patterns:\n\n**JavaScript**:\n```javascript\nfetch('/wp-json/extrachill/v1/users/search?search=username', {\n    method: 'GET',\n    headers: {\n        'X-WP-Nonce': wpApiSettings.nonce\n    }\n})\n.then(response =\u003e response.json())\n.then(data =\u003e console.log(data));\n```\n\n**PHP**:\n```php\n$response = wp_remote_get(\n    rest_url('extrachill/v1/users/search'),\n    ['body' =\u003e ['search' =\u003e 'username']]\n);\n```\n\n## Architecture\n\n### Singleton Pattern\nThe plugin uses a singleton class to manage route discovery and prevent duplicate registrations:\n\n```php\nExtraChill_API_Plugin::get_instance();\n```\n\n### Automatic Route Discovery\nRoutes are automatically loaded using PHP's RecursiveIteratorIterator:\n- Scans `inc/routes/` directory recursively\n- Loads all PHP files via `require_once`\n- Supports nested directory organization\n- Routes self-register using WordPress REST API\n\n### Action Hooks\n- `extrachill_api_bootstrap` - Initialization during `plugins_loaded`\n- `extrachill_api_register_routes` - Route registration during `rest_api_init`\n\n## Directory Structure\n\n```\nextrachill-api/\n├── extrachill-api.php          # Main plugin file\n├── build.sh                    # Production build script (symlink)\n├── composer.json               # Dependencies and scripts\n├── .buildignore               # Build exclusions\n├── CLAUDE.md                  # Technical documentation for AI agents\n├── README.md                  # This file\n└── inc/\n    ├── auth/\n    │   └── extrachill-link-auth.php    # Cross-domain authentication helper\n    ├── activity/                        # Activity system components\n    │   ├── db.php\n    │   ├── emitter.php\n    │   ├── emitters.php\n    │   ├── schema.php\n    │   ├── storage.php\n    │   ├── taxonomies.php\n    │   └── throttle.php\n    ├── controllers/\n    │   └── class-docs-sync-controller.php\n    ├── utils/\n    │   ├── bbpress-drafts.php\n    │   └── id-generator.php\n    └── routes/\n        ├── admin/\n        │   ├── 404-logger.php\n        │   ├── lifetime-membership.php\n        │   ├── artist-access.php\n        │   ├── artist-relationships.php\n        │   ├── forum-topics.php\n        │   ├── tags.php\n        │   ├── taxonomy-sync.php\n        │   └── team-members.php\n        ├── activity/\n        │   ├── feed.php\n        │   └── object.php\n        ├── analytics/\n        │   ├── click.php\n        │   ├── link-page.php\n        │   └── view-count.php\n        ├── artists/\n        │   ├── analytics.php\n        │   ├── artist.php\n        │   ├── links.php\n        │   ├── permissions.php\n        │   ├── roster.php\n        │   ├── socials.php\n        │   ├── subscribe.php\n        │   └── subscribers.php\n        ├── auth/\n        │   ├── browser-handoff.php\n        │   ├── google.php\n        │   ├── login.php\n        │   ├── logout.php\n        │   ├── me.php\n        │   ├── refresh.php\n        │   └── register.php\n        ├── blog/\n        │   ├── ai-adventure.php\n        │   ├── band-name.php\n        │   ├── image-voting.php\n        │   ├── image-voting-vote.php\n        │   └── rapper-name.php\n        ├── chat/\n        │   ├── history.php\n        │   └── message.php\n        ├── community/\n        │   ├── drafts.php\n        │   └── upvote.php\n        ├── config/\n        │   └── oauth.php\n        ├── contact/\n        │   └── submit.php\n        ├── docs/\n        │   └── docs-info.php\n        ├── docs-sync-routes.php\n        ├── events/\n        │   └── event-submissions.php\n        ├── media/\n        │   └── upload.php\n        ├── newsletter/\n        │   ├── campaign.php\n        │   └── subscription.php\n        ├── seo/\n        │   ├── audit.php\n        │   ├── continue.php\n        │   ├── status.php\n        │   ├── details.php\n        │   └── config.php\n        ├── shop/\n        │   ├── orders.php\n        │   ├── product-images.php\n        │   ├── products.php\n        │   ├── shipping-address.php\n        │   ├── shipping-labels.php\n        │   ├── stripe-connect.php\n        │   └── stripe-webhook.php\n        ├── stream/\n        │   └── status.php\n        ├── tools/\n        │   ├── qr-code.php\n        │   └── markdown-export.php\n        └── users/\n            ├── artists.php\n            ├── leaderboard.php\n            ├── onboarding.php\n            ├── search.php\n            └── users.php\n```\n\n## Development\n\n### Production Build\n```bash\n./build.sh\n```\n\n### Testing Endpoints\n```bash\nwp rest list\n```\n\n## Integration\n\n### Current Plugin Integrations\n\n**extrachill-blog**:\n- Image voting vote counts and voting\n- AI Adventure story generation\n- Band/Rapper name generators\n\n**extrachill-community**:\n- User search for @mentions\n- Community upvoting\n- Draft management for topics and replies\n\n**extrachill-events**:\n- Event submission block posts to the `/event-submissions` route\n\n**extrachill-users**:\n- Avatar upload via media endpoint\n- User profile and search functionality\n\n**extrachill-shop**:\n- Product CRUD operations\n- Stripe Connect management\n\n**extrachill-newsletter**:\n- Newsletter subscription endpoint\n- Campaign push to Sendy\n\n## Security\n\nAll endpoints implement WordPress REST API security standards:\n- **Nonce Verification**: WordPress REST API nonce system\n- **Permission Callbacks**: User capability checks\n- **Input Validation**: Parameter validation callbacks\n- **Sanitization**: All user input sanitized\n- **Output Escaping**: Responses via `rest_ensure_response()`\n\n## Performance\n\n- Route files load once via `require_once` on plugin init\n- Per-endpoint performance depends on the underlying query and site context (some endpoints switch blog context)\n\n## Dependencies\n\n**Runtime**:\n- WordPress multisite\n\n**Optional integrations**:\n- WooCommerce (required by some `/shop/*` routes, in the shop site context)\n- `extrachill-multisite` (provides shared multisite helpers used by some routes)\n- `extrachill-ai-client` (used by AI generator routes when enabled)\n\n## Hooks\n\n### `extrachill_event_submission`\n\nFires after a submission is validated, optional flyer stored, and a Data Machine job is queued.\n\n```php\nadd_action( 'extrachill_event_submission', function( array $submission, array $context ) {\n    // $submission contains sanitized form data + optional flyer metadata\n    // $context includes flow_id, job_id, action_id, flow_name\n} );\n```\n\nUse the hook to notify editors, trigger Slack alerts, or log analytics without reimplementing REST validation.\n\n## Documentation\n\n- **[CLAUDE.md](CLAUDE.md)** - Comprehensive technical documentation for AI agents\n- **[Root CLAUDE.md](../../CLAUDE.md)** - Platform-wide architectural patterns\n- **[WordPress REST API Handbook](https://developer.wordpress.org/rest-api/)** - Official REST API documentation\n\n## Support\n\nFor issues, questions, or feature requests related to the Extra Chill Platform:\n- **Primary Contact**: Chris Huber - [chubes.net](https://chubes.net)\n- **Organization**: [Extra Chill](https://github.com/Extra-Chill)\n- **Main Site**: [extrachill.com](https://extrachill.com)\n\n## License\n\nGPL v2 or later\n\n## Changelog\n\nSee [docs/CHANGELOG.md](docs/CHANGELOG.md) for full version history.\n\n---\n\n**Part of the Extra Chill Platform** - WordPress multisite ecosystem for music community\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fextra-chill%2Fextrachill-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fextra-chill%2Fextrachill-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fextra-chill%2Fextrachill-api/lists"}