API Documentation
Everything you need to integrate with the Tampa.dev platform.
Webhooks
Webhooks let you receive real-time HTTP POST notifications when events occur on the platform. Register webhooks in the Developer Portal.
Event Types
Platform Events
| Event Type | Description | Access |
|---|---|---|
dev.tampa.events.synced | Events were synced from an upstream source | Public |
dev.tampa.sync.completed | A full platform sync completed | Public |
dev.tampa.user.favorite_added | A user favorited a group | Public |
dev.tampa.user.favorite_removed | A user unfavorited a group | Public |
dev.tampa.user.profile_updated | A user updated their profile | Public |
dev.tampa.user.portfolio_item_created | A user added a portfolio item | Public |
dev.tampa.user.identity_linked | A user linked an identity provider | Admin only |
dev.tampa.user.registered | A new user registered | Admin only |
dev.tampa.user.deleted | A user deleted their account | Admin only |
dev.tampa.achievement.unlocked | A user completed an achievement | Admin only |
dev.tampa.badge.issued | A badge was awarded to a user | Admin only |
dev.tampa.user.score_changed | A user's XP score changed | Admin only |
dev.tampa.user.login | A user logged in | Public |
dev.tampa.user.followed | A user followed another user | Public |
dev.tampa.onboarding.step_completed | A user completed an onboarding step | Public |
dev.tampa.onboarding.completed | A user completed all onboarding | Admin only |
dev.tampa.developer.api_token_created | A developer created an API token | Public |
dev.tampa.developer.webhook_created | A developer created a webhook | Public |
dev.tampa.developer.application_registered | A developer registered an OAuth app | Public |
test.ping | Test webhook delivery | Public |
Group Management Events
| Event Type | Description | Access |
|---|---|---|
dev.tampa.group.created | A new group was created | Admin only |
dev.tampa.group.updated | A group's settings were updated | Admin only |
dev.tampa.group.member_added | A user was added to a group | Public |
dev.tampa.group.member_removed | A user was removed from a group | Public |
dev.tampa.group.member_role_changed | A member's role was changed | Public |
dev.tampa.group.claimed | A group was claimed by a user | Admin only |
dev.tampa.group.creation_requested | A group creation request was submitted | Admin only |
Group Badge Events
| Event Type | Description | Access |
|---|---|---|
dev.tampa.group.badge_created | A group badge was created | Admin only |
dev.tampa.group.badge_updated | A group badge was updated | Public |
dev.tampa.group.badge_deleted | A group badge was deleted | Admin only |
Event Management Events
| Event Type | Description | Access |
|---|---|---|
dev.tampa.event.created | A native event was created | Public |
dev.tampa.event.updated | An event was updated | Public |
dev.tampa.event.cancelled | An event was cancelled | Public |
dev.tampa.event.rsvp | A user RSVP'd to an event | Public |
dev.tampa.event.rsvp_cancelled | A user cancelled their RSVP | Public |
dev.tampa.event.checkin | A user checked in to an event | Public |
Admin-restricted events require an admin or superadmin role to subscribe. Regular users will receive a 403 error if they attempt to create webhooks for these event types.
Payload Format
Every webhook delivery sends a JSON payload with this structure:
{
"id": "delivery-uuid",
"type": "dev.tampa.events.synced",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": { ... }
}
Payload Schemas by Event Type
dev.tampa.events.synced
Fired when events are synced from an upstream source (e.g., Meetup, Eventbrite).
{
"id": "d1e2f3a4-...",
"type": "dev.tampa.events.synced",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": {
"source": "meetup",
"eventsCount": 42,
"groupSlug": "tampa-devs"
}
}
dev.tampa.sync.completed
Fired when a full platform sync completes across all sources.
{
"id": "d1e2f3a4-...",
"type": "dev.tampa.sync.completed",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": {
"totalEvents": 156,
"totalGroups": 12,
"duration": 4500
}
}
dev.tampa.user.favorite_added
Fired when a user favorites a group.
{
"id": "d1e2f3a4-...",
"type": "dev.tampa.user.favorite_added",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": {
"userId": "user-uuid",
"groupSlug": "tampa-devs",
"groupName": "Tampa Devs"
}
}
dev.tampa.user.profile_updated
Fired when a user updates their profile (name, username, bio, social links, etc.).
{
"id": "d1e2f3a4-...",
"type": "dev.tampa.user.profile_updated",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": {
"userId": "user-uuid",
"fields": ["username", "bio", "socialLinks"]
}
}
dev.tampa.user.portfolio_item_created
Fired when a user adds a portfolio item.
{
"id": "d1e2f3a4-...",
"type": "dev.tampa.user.portfolio_item_created",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": {
"userId": "user-uuid",
"itemId": "item-uuid",
"title": "My Project"
}
}
Admin-Restricted Events
Payload schemas for admin-restricted event types (dev.tampa.user.identity_linked, dev.tampa.user.registered, dev.tampa.user.deleted, dev.tampa.achievement.unlocked, dev.tampa.badge.issued, dev.tampa.user.score_changed) are documented in the admin panel under Admin Docs.
Group Management Events
dev.tampa.group.created
Fired when a new native group is created.
{
"id": "d1e2f3a4-...",
"type": "dev.tampa.group.created",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": {
"groupId": "group-uuid",
"groupName": "My Group",
"createdBy": "user-uuid"
}
}
dev.tampa.group.updated
Fired when a group's settings are updated.
{
"id": "d1e2f3a4-...",
"type": "dev.tampa.group.updated",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": {
"groupId": "group-uuid",
"fields": ["name", "description", "tags"]
}
}
dev.tampa.group.member_added
Fired when a user is added to a group.
{
"id": "d1e2f3a4-...",
"type": "dev.tampa.group.member_added",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": {
"groupId": "group-uuid",
"userId": "user-uuid",
"role": "member",
"addedBy": "manager-uuid"
}
}
dev.tampa.group.member_removed
Fired when a user is removed from a group (or leaves voluntarily).
{
"id": "d1e2f3a4-...",
"type": "dev.tampa.group.member_removed",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": {
"groupId": "group-uuid",
"userId": "user-uuid",
"removedBy": "manager-uuid"
}
}
dev.tampa.group.member_role_changed
Fired when a member's role is updated.
{
"id": "d1e2f3a4-...",
"type": "dev.tampa.group.member_role_changed",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": {
"groupId": "group-uuid",
"userId": "user-uuid",
"oldRole": "member",
"newRole": "manager",
"changedBy": "owner-uuid"
}
}
dev.tampa.group.claimed
Fired when a group is claimed via an invite link.
{
"id": "d1e2f3a4-...",
"type": "dev.tampa.group.claimed",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": {
"groupId": "group-uuid",
"userId": "user-uuid",
"method": "invite",
"autoApproved": true
}
}
dev.tampa.group.creation_requested
Fired when a user submits a group creation or claim request.
{
"id": "d1e2f3a4-...",
"type": "dev.tampa.group.creation_requested",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": {
"requestId": "request-uuid",
"userId": "user-uuid",
"groupName": "My New Group",
"type": "creation"
}
}
The type field is "creation" for new group requests or "claim" for ownership claim requests.
dev.tampa.group.badge_created
Fired when a group badge is created.
{
"id": "d1e2f3a4-...",
"type": "dev.tampa.group.badge_created",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": {
"groupId": "group-uuid",
"badgeId": "badge-uuid",
"badgeSlug": "contributor",
"badgeName": "Contributor"
}
}
Event Management Events
dev.tampa.event.created
Fired when a native event is created.
{
"id": "d1e2f3a4-...",
"type": "dev.tampa.event.created",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": {
"eventId": "event-uuid",
"groupId": "group-uuid",
"title": "Monthly Meetup",
"startTime": "2026-02-15T18:30:00-05:00",
"createdBy": "user-uuid"
}
}
dev.tampa.event.updated
Fired when an event is updated.
{
"id": "d1e2f3a4-...",
"type": "dev.tampa.event.updated",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": {
"eventId": "event-uuid",
"groupId": "group-uuid",
"fields": ["title", "description"],
"updatedBy": "user-uuid"
}
}
dev.tampa.event.cancelled
Fired when an event is cancelled.
{
"id": "d1e2f3a4-...",
"type": "dev.tampa.event.cancelled",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": {
"eventId": "event-uuid",
"groupId": "group-uuid",
"title": "Monthly Meetup",
"cancelledBy": "user-uuid"
}
}
dev.tampa.event.rsvp
Fired when a user RSVPs to an event, or when a waitlisted user is promoted.
{
"id": "d1e2f3a4-...",
"type": "dev.tampa.event.rsvp",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": {
"eventId": "event-uuid",
"userId": "user-uuid",
"status": "confirmed",
"waitlistPosition": null
}
}
When a waitlisted user is automatically promoted (because a confirmed user cancelled), the payload includes "promotedFromWaitlist": true.
dev.tampa.event.rsvp_cancelled
Fired when a user cancels their RSVP.
{
"id": "d1e2f3a4-...",
"type": "dev.tampa.event.rsvp_cancelled",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": {
"eventId": "event-uuid",
"userId": "user-uuid",
"previousStatus": "confirmed"
}
}
dev.tampa.event.checkin
Fired when a user checks in to an event.
{
"id": "d1e2f3a4-...",
"type": "dev.tampa.event.checkin",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": {
"eventId": "event-uuid",
"userId": "user-uuid",
"checkinCodeId": "code-uuid",
"method": "link"
}
}
The method field indicates how the user checked in: link (clicked a URL), qr (scanned a QR code), or nfc (tapped an NFC tag).
dev.tampa.user.login
Fired when a user logs in.
{
"id": "d1e2f3a4-...",
"type": "dev.tampa.user.login",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": {
"userId": "user-uuid",
"daysSinceCreation": 42
}
}
dev.tampa.user.followed
Fired when a user follows another user.
{
"id": "d1e2f3a4-...",
"type": "dev.tampa.user.followed",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": {
"userId": "follower-uuid",
"followedUserId": "followed-uuid"
}
}
dev.tampa.developer.api_token_created
Fired when a developer creates an API token.
{
"id": "d1e2f3a4-...",
"type": "dev.tampa.developer.api_token_created",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": {
"userId": "user-uuid",
"tokenId": "token-uuid",
"tokenName": "My API Token"
}
}
dev.tampa.developer.webhook_created
Fired when a developer creates a webhook.
{
"id": "d1e2f3a4-...",
"type": "dev.tampa.developer.webhook_created",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": {
"userId": "user-uuid",
"webhookId": "webhook-uuid",
"url": "https://example.com/webhook"
}
}
dev.tampa.developer.application_registered
Fired when a developer registers an OAuth application.
{
"id": "d1e2f3a4-...",
"type": "dev.tampa.developer.application_registered",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": {
"userId": "user-uuid",
"clientId": "client-id",
"appName": "My App"
}
}
test.ping
Test event for verifying webhook connectivity. Sent via the "Send Test" button in the Developer Portal.
{
"id": "d1e2f3a4-...",
"type": "test.ping",
"timestamp": "2026-01-29T12:00:00.000Z",
"data": {
"message": "Hello from Tampa.dev!"
}
}
Headers
| Header | Description |
|---|---|
X-Webhook-Signature | HMAC-SHA256 signature: sha256=hex_digest |
X-Event-Type | The event type (e.g. dev.tampa.events.synced) |
X-Delivery-ID | Unique delivery identifier |
Content-Type | application/json |
User-Agent | TampaDevs-Webhooks/1.0 |
Signature Verification
Verify the X-Webhook-Signature header by computing HMAC-SHA256 of the raw request body using your webhook secret:
const crypto = require('crypto');
function verifySignature(body, secret, signature) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
Always verify signatures before processing webhook payloads to ensure they originated from Tampa.dev.
Testing Webhooks
You can send test deliveries from the Developer Portal. The test UI lets you select a specific event type to simulate, generating a realistic payload for that event type. This helps you verify your webhook handler processes each event type correctly.
Retry Policy
If your endpoint returns a non-2xx status code or fails to respond, delivery is retried up to 3 times with exponential backoff. You can view delivery history in the Developer Portal.