REST API Reference
Eventonomy is 100% REST - there is no admin-ajax.php usage anywhere. Every UI surface (blocks, admin console, CLI) hits the same endpoints. Third-party code uses the same contract.
Canonical contract:
docs/REST-API.mdin the plugin root is the authoritative specification. This page is a navigable summary with key examples. When anything here conflicts with the source file, the source file wins.
What You Will Learn
- Base URL, namespace, and authentication strategies
- The canonical list-response envelope
- All resources: Events, Occurrences, RSVPs, Tickets, Orders, ICS, App Config, Bulk
- Pagination strategies (cursor vs. offset)
- The error contract
Conventions
| Concern | Value |
|---|---|
| REST namespace | eventonomy/v1 |
| Base URL | /wp-json/eventonomy/v1/ |
| HTTP methods | GET (read), POST (create), PATCH (partial update), DELETE (delete). No PUT. |
| Timestamps | ISO 8601 UTC. Never a field named date. |
Authentication
First-Party (Cookie + Nonce)
Used by blocks, the frontend SPA, and in-browser clients.
fetch('/wp-json/eventonomy/v1/events', {
headers: { 'X-WP-Nonce': eventonomyData.nonce },
credentials: 'same-origin'
});
Headless (Application Passwords)
Used by external integrations, mobile apps, and server-to-server calls. Requires HTTPS.
curl -u "jane:abcd EFGH ijkl MNOP qrst UVWX" \
https://example.com/wp-json/eventonomy/v1/events
Public Endpoints
No auth required: GET /events (published only), GET /events/{id} (published), GET /occurrences, GET /events/{id}.ics, GET /calendar.ics, GET /settings/app-config, the magic-link RSVP flow.
The List Envelope
Every list endpoint returns the same uniform envelope:
{
"items": [ /* resource objects */ ],
"total": 124,
"pages": 11,
"has_more": true,
"next_cursor": "470"
}
Cursor lists set total and pages to null unless ?with_total=1 is passed.
Resources
Events - /events
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /events |
Public (published) | List events. Cursor pagination. |
| GET | /events/{id} |
Public (published) | Single event detail. |
| POST | /events |
evnm_create_events |
Create an event. |
| PATCH | /events/{id} |
Owner or evnm_manage_events |
Partial update. |
| DELETE | /events/{id} |
Owner or evnm_manage_events |
Soft-delete (trash) or force-delete. |
Key list parameters: from, to, category, tag, organizer, city, featured, search, status, author, cursor, page, per_page, fields (card|detail).
Occurrences - /occurrences
Calendar query endpoint. Returns occurrence rows joined to a compact event summary.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /occurrences |
Public | Calendar list. Cursor pagination on (id). |
| GET | /events/{id}/occurrences |
Public | Occurrences for one event. |
| PATCH | /occurrences/{id} |
Event owner or evnm_manage_events |
Update a single occurrence. |
| DELETE | /occurrences/{id} |
Event owner or evnm_manage_events |
Soft-cancel an occurrence. |
Key parameters: from, to, category, venue, cursor, per_page.
RSVPs - /rsvps
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /events/{id}/rsvp |
Logged-in or guest (name+email) | Create/update RSVP. Idempotent per identity. |
| POST | /occurrences/{id}/rsvp |
Logged-in or guest | Occurrence-scoped RSVP. |
| DELETE | /events/{id}/rsvp |
RSVP owner or magic-link token | Cancel RSVP. Triggers waitlist promotion. |
| GET | /events/{id}/attendees |
evnm_manage_rsvps |
Attendee list. Cursor pagination. |
| POST | /rsvp/magic-link |
Public (rate-limited) | Request a management link by email. |
| GET | /rsvp/verify |
Public (token is credential) | Verify token; returns RSVP + session token. |
| PATCH | /rsvp/manage |
Token in body or header | Update RSVP via token. |
RSVP statuses: going, maybe, no, waitlist.
Tickets - /events/{id}/tickets
| Method | Path | Auth |
|---|---|---|
| GET | /events/{id}/tickets |
Public |
| POST | /events/{id}/tickets |
evnm_manage_tickets |
| PATCH | /events/{id}/tickets/{ticket_id} |
evnm_manage_tickets |
| DELETE | /events/{id}/tickets/{ticket_id} |
evnm_manage_tickets |
Ticket types: free, donation, paid. Defining paid tickets is allowed in Free; selling them returns 402 evnm_pro_required.
Orders - /orders
| Method | Path | Auth |
|---|---|---|
| POST | /orders |
Logged-in or guest |
| GET | /orders/{id} |
Order owner or evnm_manage_orders |
| GET | /orders |
evnm_manage_orders (event-scoped for organizers) |
Free completes only $0 orders. Orders with total > 0 return 402 evnm_pro_required.
ICS Feeds
GET /events/{id}.ics # single event download
GET /calendar.ics # subscribable feed (supports from, to, category, organizer, venue, token)
App Config
GET /settings/app-config # public bootstrap - features, currency, timezone, is_pro_active
Bulk Operations
POST /events/bulk # ids (max 50), action (publish|draft|trash|delete|feature|unfeature)
Pagination
| Endpoint | Strategy |
|---|---|
GET /events |
Cursor (default); offset via ?page= |
GET /occurrences |
Cursor |
GET /events/{id}/attendees |
Cursor |
GET /events/{id}/tickets |
Offset |
GET /orders |
Offset |
Cursor parameters: ?cursor=<opaque_id>, ?per_page=. Offset parameters: ?page=, ?per_page=. Default per_page = 12, max = 100.
Error Contract
All errors use WP_Error with an evnm_ code prefix:
{
"code": "evnm_not_found",
"message": "Event not found.",
"data": { "status": 404 }
}
Validation errors (422) include per-field detail under data.errors.
Common codes: evnm_unauthorized (401), evnm_forbidden (403), evnm_not_found (404), evnm_validation_failed (422), evnm_rsvp_closed (409), evnm_capacity_full (409), evnm_pro_required (402), evnm_rate_limited (429), evnm_bulk_limit (422).
Adding Your Own Endpoints
Register in any namespace and reuse Eventonomy services via evnm():
add_action( 'rest_api_init', function () {
register_rest_route( 'my-addon/v1', '/events/(?P<id>\d+)/my-data', [
'methods' => 'GET',
'permission_callback' => '__return_true',
'callback' => function ( $req ) {
$event = evnm( \Eventonomy\Contracts\EventRepositoryInterface::class )
->get( (int) $req['id'] );
return rest_ensure_response( [ 'event_id' => $event['id'] ] );
},
] );
} );
What's Next?
Browse the full hook and filter catalog.