API Documentation
Everything you need to integrate with the Tampa.dev platform.
Groups & Badges
Groups
GET /v1/groups
List groups. Scope: read:groups.
curl -H "Authorization: Bearer td_pat_abc123..." \
"https://api.tampa.dev/v1/groups?featured=1&limit=10"
Query parameters:
| Parameter | Type | Description |
|---|---|---|
featured | 0 | 1 | Filter to featured groups |
search | string | Search by group name |
limit | integer | Max 100, default 20 |
offset | integer | Pagination offset |
{
"data": [
{
"id": "grp_react",
"urlname": "react-tampa",
"name": "React Tampa",
"description": "Tampa's React developer community",
"link": "https://meetup.com/react-tampa",
"website": "https://react-tampa.dev",
"memberCount": 450,
"photoUrl": "https://cdn.tampa.dev/groups/react-tampa.jpg",
"tags": ["react", "javascript", "frontend"],
"socialLinks": ["https://twitter.com/reacttampa"]
}
],
"pagination": {
"total": 25,
"limit": 10,
"offset": 0,
"hasMore": true
}
}
GET /v1/groups/:slug
Get group details with upcoming events. Scope: read:groups.
curl -H "Authorization: Bearer td_pat_abc123..." \
https://api.tampa.dev/v1/groups/react-tampa
{
"data": {
"id": "grp_react",
"urlname": "react-tampa",
"name": "React Tampa",
"description": "Tampa's React developer community",
"link": "https://meetup.com/react-tampa",
"website": "https://react-tampa.dev",
"memberCount": 450,
"photoUrl": "https://cdn.tampa.dev/groups/react-tampa.jpg",
"tags": ["react", "javascript", "frontend"],
"socialLinks": ["https://twitter.com/reacttampa"],
"upcomingEvents": [
{
"id": "evt_abc123",
"title": "React Tampa Monthly Meetup",
"startTime": "2026-02-15T18:30:00-05:00",
"eventUrl": "https://meetup.com/react-tampa/events/123"
}
]
}
}
Favorites
GET /v1/favorites
List the authenticated user's favorite groups. Scope: read:favorites.
curl -H "Authorization: Bearer td_pat_abc123..." \
https://api.tampa.dev/v1/favorites
{
"data": [
{
"id": "grp_react",
"urlname": "react-tampa",
"name": "React Tampa",
"description": "Tampa's React developer community",
"photoUrl": "https://cdn.tampa.dev/groups/react-tampa.jpg",
"memberCount": 450
}
],
"pagination": {
"total": 3,
"limit": 20,
"offset": 0,
"hasMore": false
}
}
POST /v1/favorites/:groupSlug
Add a group to favorites. Scope: write:favorites.
curl -X POST \
-H "Authorization: Bearer td_pat_abc123..." \
https://api.tampa.dev/v1/favorites/react-tampa
New favorite (201 Created):
{
"data": {
"groupSlug": "react-tampa"
}
}
Already favorited (200 OK):
{
"data": {
"alreadyFavorited": true
}
}
DELETE /v1/favorites/:groupSlug
Remove a group from favorites. Scope: write:favorites. Returns 204 No Content.
curl -X DELETE \
-H "Authorization: Bearer td_pat_abc123..." \
https://api.tampa.dev/v1/favorites/react-tampa
Badges
These endpoints are public and do not require authentication.
GET /badges
List all badges.
curl https://api.tampa.dev/badges
Badge responses include points, awardedCount, and a rarity object with tier and percentage fields. Rarity tiers: legendary (under 1%), epic (1-5%), rare (5-15%), uncommon (15-50%), common (50%+). Badges with hideFromDirectory enabled are excluded from the public listing.
GET /badges/:slug
Get badge details.
curl https://api.tampa.dev/badges/first-event
Badge Claiming
GET /v1/claim/:code
Get badge info for a claim link. No authentication required.
curl https://api.tampa.dev/v1/claim/BADGE-CODE-123
{
"data": {
"badge": {
"name": "Workshop Attendee",
"slug": "workshop-attendee",
"description": "Attended a Tampa Devs workshop",
"icon": "award",
"iconUrl": "https://td-uploads-public.tampa.dev/emoji/1f3c6.webp",
"color": "#FF6B6B",
"points": 50
},
"group": {
"name": "Tampa Devs",
"urlname": "tampadevs",
"photoUrl": "https://cdn.tampa.dev/groups/tampadevs.jpg"
},
"claimable": true
}
}
If the link is expired or exhausted, claimable is false and a reason field explains why.
POST /v1/claim/:code
Claim a badge. Scope: read:user.
curl -X POST \
-H "Authorization: Bearer td_pat_abc123..." \
https://api.tampa.dev/v1/claim/BADGE-CODE-123
{
"data": {
"badge": {
"name": "Workshop Attendee",
"slug": "workshop-attendee"
}
}
}
Possible errors:
409 Conflict-- Badge already claimed410 Gone-- Claim link expired or uses exhausted
Leaderboard
These endpoints are public and do not require authentication.
GET /leaderboard
Get the platform XP leaderboard.
curl "https://api.tampa.dev/leaderboard?limit=10"
Query parameters:
limit-- Number of entries (default 50, max 100)offset-- Pagination offset (default 0)
Returns users ranked by platform XP score (sum of badge point values, excluding group-scoped badges), with achievement completion counts and totalAchievements.
GET /groups/:slug/leaderboard
Get a group's XP leaderboard.
curl "https://api.tampa.dev/groups/tampadevs/leaderboard?limit=10"
Returns users ranked by group XP (sum of badge points for badges scoped to this group). Only public users with usernames are included.
User Group Badges
GET /users/:username/group-badges
Get a user's group-scoped badges, organized by group.
curl https://api.tampa.dev/users/janedev/group-badges
{
"groups": [
{
"groupId": "grp_td",
"groupName": "Tampa Devs",
"groupSlug": "tampadevs",
"groupPhotoUrl": "https://cdn.tampa.dev/groups/tampadevs.jpg",
"totalXp": 150,
"badges": [
{
"name": "Workshop Attendee",
"slug": "workshop-attendee",
"points": 50,
"awardedAt": "2025-11-15T19:00:00Z"
}
]
}
]
}
Group Claims
| Method | Endpoint | Description |
|---|---|---|
GET | /groups/claim/:token | Get group info for a claim invite |
POST | /groups/claim/:token | Accept a claim invite (requires authentication) |
POST | /groups/:groupId/claim | Submit a claim request (requires authentication) |
Claim invites can be configured with autoApprove -- if enabled, accepting the invite immediately grants ownership. Otherwise, a claim request is created for admin review.
Scopes Discovery
GET /v1/scopes
List all available OAuth scopes. No authentication required.
curl https://api.tampa.dev/v1/scopes
{
"data": [
{
"name": "user",
"description": "Read/write access to profile info (includes user:email and read:user)",
"implies": ["read:user", "user:email"]
},
{
"name": "read:events",
"description": "Read events and event details",
"implies": []
}
]
}