REST API v1
The MeerkatMeet API provides programmatic access to platform data.
All endpoints are under /api/v1 and return JSON.
Authentication
Pass your API key in the Authorization header of every request:
Authorization: Bearer YOUR_API_KEY
All requests are rate-limited to 60 requests per minute per key.
Exceeding this limit returns 429 Too Many Requests.
Error Responses
| Status | Meaning |
|---|---|
| 401 | Missing or invalid API key |
| 403 | Key is valid but you lack permission for this resource |
| 404 | Resource not found |
| 422 | Validation error (see errors field in response) |
| 429 | Rate limit exceeded |
Pagination
List endpoints return paginated results. Use the per_page query parameter (default: 25, max: 100)
and navigate pages with the page parameter.
Responses include meta and links objects.
{
"data": [ ... ],
"links": { "first": "...", "last": "...", "prev": null, "next": "..." },
"meta": { "current_page": 1, "last_page": 4, "per_page": 25, "total": 87 }
}
Users
Admin only.
/api/v1/users
List all users (paginated).
| Parameter | Type | Required | Description |
|---|---|---|---|
| per_page | integer | optional | Results per page (default 25). |
| page | integer | optional | Page number. |
{
"data": [
{
"id": 1,
"name": "Alice Smith",
"email": "alice@example.com",
"avatar": null,
"location": "Portland, OR",
"bio": "Loves hiking.",
"is_admin": false,
"owned_groups_count": 2,
"groups_count": 5,
"created_at": "2025-01-15T10:30:00+00:00",
"updated_at": "2025-03-20T08:00:00+00:00"
}
],
"meta": { "current_page": 1, "total": 42 }
}
/api/v1/users/{id}
Get a single user by ID.
{
"data": {
"id": 1,
"name": "Alice Smith",
"email": "alice@example.com",
"avatar": null,
"location": "Portland, OR",
"bio": "Loves hiking.",
"is_admin": false,
"owned_groups_count": 2,
"groups_count": 5,
"created_at": "2025-01-15T10:30:00+00:00",
"updated_at": "2025-03-20T08:00:00+00:00"
}
}
Groups
Admins see all groups. Group owners see only their own groups.
/api/v1/groups
List groups (paginated).
| Parameter | Type | Required | Description |
|---|---|---|---|
| per_page | integer | optional | Results per page (default 25). |
| page | integer | optional | Page number. |
{
"data": [
{
"id": 3,
"name": "Portland Trail Runners",
"slug": "portland-trail-runners",
"description": "<p>Weekly trail runs...</p>",
"description_plain": "Weekly trail runs...",
"location": "Portland, OR",
"latitude": 45.5051,
"longitude": -122.6750,
"status": "approved",
"requires_approval": false,
"banner_image": null,
"logo": null,
"owner": { "id": 1, "name": "Alice Smith" },
"members_count": 34,
"events_count": 12,
"created_at": "2025-02-01T00:00:00+00:00",
"updated_at": "2025-04-10T00:00:00+00:00"
}
]
}
/api/v1/groups/{id}
Get a single group by ID.
Events
Admins see all events. Group owners see events for their groups only.
/api/v1/events
List events ordered by start time descending (paginated).
| Parameter | Type | Required | Description |
|---|---|---|---|
| group_id | integer | optional | Filter events to a specific group. |
| per_page | integer | optional | Results per page (default 25). |
| page | integer | optional | Page number. |
{
"data": [
{
"id": 12,
"title": "Saturday Morning Run",
"slug": "saturday-morning-run-a1b2c3",
"description": "<p>Meet at the trailhead...</p>",
"description_plain": "Meet at the trailhead...",
"image": null,
"location": "Forest Park Trailhead, Portland, OR",
"latitude": 45.5466,
"longitude": -122.7612,
"start_time": "2025-05-03T08:00:00+00:00",
"end_time": "2025-05-03T10:00:00+00:00",
"capacity": 20,
"is_online": false,
"online_url": null,
"group_id": 3,
"user_id": 1,
"rsvps_count": 14,
"group": { "id": 3, "name": "Portland Trail Runners" },
"organizer": { "id": 1, "name": "Alice Smith" },
"created_at": "2025-04-01T00:00:00+00:00",
"updated_at": "2025-04-15T00:00:00+00:00"
}
]
}
/api/v1/events/{id}
Get a single event by ID. Includes attendees_count (RSVPs with status "going").
/api/v1/events
Create a new event. The creator is automatically RSVPed as "going". Group members are notified.
| Parameter | Type | Required | Description |
|---|---|---|---|
| group_id | integer | required | ID of the group this event belongs to. Must be a group you own (or any group if admin). |
| title | string | required | Event title (max 255 characters). |
| description | string | optional | Event description (max 20,000 characters, HTML allowed). |
| location | string | optional | Venue or address (max 255 characters). |
| start_time | datetime | required | ISO 8601 datetime. Must be now or in the future. |
| end_time | datetime | optional | ISO 8601 datetime. Must be after start_time. |
| capacity | integer | optional | Maximum number of attendees (min 1). |
| is_online | boolean | optional | Whether the event is online (default false). |
| online_url | url | optional | URL for online events. |
// Request body
{
"group_id": 3,
"title": "Saturday Morning Run",
"start_time": "2025-05-03T08:00:00Z",
"end_time": "2025-05-03T10:00:00Z",
"location": "Forest Park Trailhead, Portland, OR",
"capacity": 20
}
// Response: 201 Created
{
"data": { ... event object ... }
}
RSVPs
Admins see all RSVPs. Group owners see RSVPs for their groups' events only.
/api/v1/rsvps
List RSVPs (paginated).
| Parameter | Type | Required | Description |
|---|---|---|---|
| per_page | integer | optional | Results per page (default 25). |
| page | integer | optional | Page number. |
{
"data": [
{
"id": 55,
"event_id": 12,
"user_id": 7,
"status": "going",
"created_at": "2025-04-20T14:00:00+00:00"
}
]
}
Comments
Admin only.
/api/v1/comments
List all comments (paginated).
| Parameter | Type | Required | Description |
|---|---|---|---|
| per_page | integer | optional | Results per page (default 25). |
| page | integer | optional | Page number. |
{
"data": [
{
"id": 8,
"body": "Great event, see you there!",
"user_id": 3,
"commentable_id": 12,
"commentable_type": "App\Models\Event",
"parent_id": null,
"created_at": "2025-04-21T09:00:00+00:00"
}
]
}
Stats
Admin only. Platform-wide aggregate counts.
/api/v1/stats
Returns platform-wide totals.
{
"data": {
"total_users": 142,
"total_groups": 18,
"total_events": 97,
"total_rsvps": 834,
"total_comments": 260,
"total_photos": 415,
"pending_join_requests": 3,
"pending_group_approvals": 1,
"upcoming_events": 12
}
}