Skip to main content

API Reference

Complete reference for all Notifer API endpoints.

Interactive Documentation

For the most up-to-date and interactive API documentation, visit:

Base URL

https://app.notifer.io

Publishing Messages

Publish Message

Publish a message to a topic.

POST /{topic}
PUT /{topic}

Headers:

Content-Type: text/plain
X-Title: Message title (optional)
X-Priority: 1-5 (optional, default: 3)
X-Tags: tag1,tag2,tag3 (optional)
Authorization: Bearer <token> (optional, for private topics)
X-API-Key: <api_key> (optional, alternative auth)

Request Body:

Plain text message content

Example:

curl -X POST https://app.notifer.io/server-alerts \
-H "X-Title: Server Down" \
-H "X-Priority: 1" \
-H "X-Tags: critical,server,production" \
-d "Production server prod-web-01 is not responding"

Response: 200 OK

{
"id": "550e8400-e29b-41d4-a716-446655440000",
"topic": "server-alerts",
"message": "Production server prod-web-01 is not responding",
"title": "Server Down",
"priority": 1,
"tags": ["critical", "server", "production"],
"timestamp": "2025-01-15T10:30:00Z"
}

Topics

List All Topics

Get all topics with statistics (public endpoint).

GET /api/topics

Query Parameters:

  • limit (int, optional): Max topics to return (default: 50, max: 100)
  • offset (int, optional): Number of topics to skip (default: 0)

Response: 200 OK

[
{
"id": "uuid",
"name": "server-alerts",
"owner_id": "uuid",
"team_id": null,
"access_level": "private",
"description": "Production server monitoring",
"is_discoverable": false,
"icon_name": "server",
"icon_color": "red",
"message_count": 42,
"subscriber_count": 5,
"created_at": "2025-01-01T00:00:00Z",
"last_message_at": "2025-01-15T10:30:00Z"
}
]

List My Topics

Get topics owned by the current user.

GET /api/topics/my

Headers:

Authorization: Bearer <token>

Query Parameters:

  • limit (int, optional): Max topics to return (default: 50, max: 100)
  • offset (int, optional): Number of topics to skip (default: 0)

Response: 200 OK (same format as List All Topics, with can_manage: true)

List Public Topics

Get all public/discoverable topics (for Discover tab).

GET /api/topics/public

Query Parameters:

  • limit (int, optional): Max topics to return (default: 50, max: 100)
  • offset (int, optional): Number of topics to skip (default: 0)

Response: 200 OK (same format as List All Topics)

Create Topic

Create a new topic.

POST /api/topics

Headers:

Authorization: Bearer <token>
Content-Type: application/json

Request Body:

{
"name": "my-topic",
"access_level": "public|private",
"description": "Topic description (required for discoverable public topics)",
"is_discoverable": true,
"icon_name": "bell",
"icon_color": "blue",
"team_id": "uuid (optional, for team topics)"
}

Response: 201 Created

{
"id": "uuid",
"name": "my-topic",
"access_level": "public",
"description": "Topic description",
"is_discoverable": true,
"created_at": "2025-01-15T10:30:00Z",
"message_count": 0,
"last_message_at": null,
"subscription_warning": null
}

Get Topic

Get topic details by name.

GET /api/topics/{name}

Response: 200 OK

{
"id": "uuid",
"name": "server-alerts",
"owner_id": "uuid",
"team_id": null,
"access_level": "private",
"description": "Production server monitoring",
"is_discoverable": false,
"icon_name": "server",
"icon_color": "red",
"message_count": 42,
"subscriber_count": 5,
"connection_count": 3,
"created_at": "2025-01-01T00:00:00Z",
"last_message_at": "2025-01-15T10:30:00Z",
"can_manage": false
}

Get Topic Stats

Get topic statistics (alias for GET /api/topics/{name}).

GET /api/topics/{name}/stats

Response: 200 OK (same format as Get Topic)

Search Topic Messages

Search or list messages in a specific topic.

GET /api/topics/{name}/messages

Query Parameters:

  • q (string, optional): Search query (searches title and message content)
  • limit (int, optional): Max messages per page (default: 50, max: 100)
  • offset (int, optional): Number of messages to skip (default: 0)
  • priority_min (int, optional): Minimum priority (1-5)
  • priority_max (int, optional): Maximum priority (1-5)
  • tags (string, optional): Filter by tags (comma-separated)
  • date_from (ISO datetime, optional): Filter messages from this date
  • date_to (ISO datetime, optional): Filter messages until this date
  • include_deleted (bool, optional): Include soft-deleted messages (default: false)

Response: 200 OK

{
"messages": [...],
"total": 150,
"limit": 50,
"offset": 0,
"query": "server down",
"topic": "alerts"
}

Update Topic

Update topic settings (owner or team admin only).

PATCH /api/topics/{topic_id}
Path Parameter

This endpoint uses the topic UUID ({topic_id}), not the topic name.

Headers:

Authorization: Bearer <token>
Content-Type: application/json

Request Body:

{
"name": "new-topic-name",
"description": "Updated description",
"is_discoverable": false,
"icon_name": "server",
"icon_color": "red",
"access_level": "private"
}

Response: 200 OK

Delete Topic

Delete a topic permanently (owner or team admin only).

DELETE /api/topics/{topic_id}
Path Parameter

This endpoint uses the topic UUID ({topic_id}), not the topic name.

Headers:

Authorization: Bearer <token>

Response: 204 No Content


Messages

Get Message History

Get message history for a topic (JSON format).

GET /{topic}/json

Query Parameters:

  • limit (int, optional): Max messages to return (default: 50)
  • since (string, optional): Get messages since this timestamp
  • poll (int, optional): Poll mode flag (0 or 1)

Headers (optional):

X-Topic-Token: <topic_access_token> (for private topics)

Example:

curl "https://app.notifer.io/server-alerts/json?limit=50"

Response: 200 OK

{
"messages": [
{
"id": "uuid",
"topic_id": "uuid",
"message": "Server is down",
"title": "Alert",
"priority": 1,
"tags": ["critical"],
"timestamp": "2025-01-15T10:30:00Z",
"expires_at": "2025-02-14T10:30:00Z",
"is_deleted": false,
"is_edited": false
}
],
"topic": "server-alerts",
"count": 1
}

Search Messages

Search messages with full-text search and filters.

GET /api/messages/search

Query Parameters:

  • q (string, optional): Search query (searches title and message content)
  • topic (string, optional): Filter by topic name
  • tags (array, optional): Filter by tags (matches ANY tag)
  • priority_min (int, optional): Minimum priority (1-5)
  • priority_max (int, optional): Maximum priority (1-5)
  • date_from (ISO datetime, optional): Filter messages after this date
  • date_to (ISO datetime, optional): Filter messages before this date
  • limit (int, optional): Max results to return (default: 50, max: 100)
  • offset (int, optional): Results offset for pagination (default: 0)

Example:

curl "https://app.notifer.io/api/messages/search?q=server&tags=critical&priority_max=2" \
-H "Authorization: Bearer $TOKEN"

Response: 200 OK

{
"messages": [...],
"total": 150,
"limit": 50,
"offset": 0,
"query": "server",
"filters": {
"topic": null,
"priority_min": null,
"priority_max": 2,
"tags": ["critical"],
"date_from": null,
"date_to": null
}
}

Get Recent Messages

Get recent messages from subscribed topics.

GET /api/messages/recent

Headers:

Authorization: Bearer <token>

Query Parameters:

  • limit (int, optional): Max messages to return (default: 100, max: 200)
  • topic (string, optional): Filter by topic name

Response: 200 OK

[
{
"id": "uuid",
"topic_id": "uuid",
"topic": "server-alerts",
"message": "Server is down",
"title": "Alert",
"priority": 1,
"tags": ["critical"],
"timestamp": "2025-01-15T10:30:00Z"
}
]

Get Message Activity

Get message activity statistics for chart visualization.

GET /api/messages/activity

Headers:

Authorization: Bearer <token>

Query Parameters:

  • start_date (ISO datetime, optional): Start of time range (default: 24h ago)
  • end_date (ISO datetime, optional): End of time range (default: now)
  • bucket (string, optional): Bucket size - "hour" or "day" (auto-selected based on range)
  • topics (string, optional): Comma-separated list of topic names
  • priority_min (int, optional): Minimum priority (1-5)
  • priority_max (int, optional): Maximum priority (1-5)
  • tags (string, optional): Comma-separated list of tags
  • query (string, optional): Search query to filter messages

Response: 200 OK

{
"buckets": [
{
"timestamp": "2025-01-15T10:00:00Z",
"priority_1": 2,
"priority_2": 5,
"priority_3": 10,
"priority_4": 3,
"priority_5": 1
}
],
"total": 150,
"bucket_size": "hour",
"start_date": "2025-01-14T10:00:00Z",
"end_date": "2025-01-15T10:00:00Z"
}

Delete Message

Soft-delete a message (owner or team admin only, ESSENTIALS+ plans).

DELETE /api/{topic_name}/messages/{message_id}

Headers:

Authorization: Bearer <token>

Response: 200 OK

{
"id": "uuid",
"deleted_at": "2025-01-15T10:30:00Z",
"message": "Message deleted successfully"
}

Edit Message

Edit a message (owner or team admin only, ESSENTIALS+ plans).

PATCH /api/{topic_name}/messages/{message_id}

Headers:

Authorization: Bearer <token>
Content-Type: application/json

Request Body:

{
"message": "Updated message content",
"title": "Updated title (optional)"
}

Response: 200 OK

{
"id": "uuid",
"message": "Updated message content",
"title": "Updated title",
"edited_at": "2025-01-15T10:30:00Z"
}

Real-time Subscriptions

Subscribe to Multiple Topics (SSE)

Subscribe to multiple topics via a single SSE connection.

GET /sse

Query Parameters:

  • session (string, recommended): Session ID from POST /api/sse/sessions
  • topics (string, alternative): Comma-separated list of topic names
  • token (string, optional): JWT or topic access token (not needed with session)
  • since_id (string, optional): Per-topic format: topic1:id1,topic2:id2

Session-based example (recommended):

// 1. Create session (POST)
const response = await fetch('/api/sse/sessions', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + token,
'Content-Type': 'application/json'
},
body: JSON.stringify({
topics: ['alerts', 'monitoring', 'deployments'],
since_id: {'alerts': 'uuid1'}
})
});
const { session_id } = await response.json();

// 2. Connect to SSE (GET with short URL)
const eventSource = new EventSource(`/sse?session=${session_id}`);

Create SSE Session

Create an SSE subscription session for short URLs.

POST /api/sse/sessions

Headers:

Authorization: Bearer <token>
Content-Type: application/json

Request Body:

{
"topics": ["alerts", "monitoring", "deployments"],
"since_id": {"alerts": "uuid1", "monitoring": "uuid2"}
}

Response: 200 OK

{
"session_id": "abc123...",
"topics": ["alerts", "monitoring", "deployments"],
"expires_in": 300
}

Subscribe to Single Topic (SSE)

Subscribe to a single topic via Server-Sent Events.

GET /{topic}/sse

Query Parameters:

  • token (string, optional): JWT token or topic access token for private topics
  • since_id (uuid, optional): Only send messages after this ID

Example:

# Public topic
curl -N https://app.notifer.io/public-topic/sse

# Private topic with JWT
curl -N "https://app.notifer.io/private-topic/sse?token=$JWT_TOKEN"

# Private topic with access token
curl -N "https://app.notifer.io/private-topic/sse?token=tk_your_token_here"

Response: SSE stream

event: ready
data: {"topic":"server-alerts","message":"Connected to topic","connection_id":"..."}

event: message
data: {"id":"uuid","topic":"server-alerts","message":"Hello",...}

event: ping
data:

Subscribe via WebSocket

Subscribe to topic via WebSocket.

WS /{topic}/ws

Query Parameters:

  • token (string, optional): JWT token or topic access token for private topics

Example:

const ws = new WebSocket('wss://app.notifer.io/my-topic/ws?token=<TOKEN>');

ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'message') {
console.log('New message:', data);
} else if (data.type === 'ping') {
// Heartbeat
}
};

Authentication

Register

Register a new user account.

POST /auth/register

Request Body:

{
"email": "user@example.com",
"username": "username",
"password": "strong-password",
"terms_accepted": true
}
Email Verification Required

Registration requires email verification. An email with a verification link will be sent to the provided address. The user must verify their email before they can log in.

Response: 201 Created

{
"message": "Registration successful. Please check your email to verify your account.",
"email": "user@example.com",
"username": "username"
}

Login

Login with email and password.

POST /auth/login

Request Body:

{
"email": "user@example.com",
"password": "password"
}

Response: 200 OK

{
"access_token": "eyJ...",
"refresh_token": "eyJ...",
"token_type": "bearer",
"user": {
"id": "uuid",
"email": "user@example.com",
"username": "username",
"subscription_tier": "FREE",
"is_verified": true,
"created_at": "2025-01-01T00:00:00Z"
}
}

Google OAuth

Initiate Google OAuth login/registration.

GET /auth/google/login

Redirects to Google OAuth flow. After successful authentication, redirects back to the callback URL with tokens.

Apple Sign-In (Mobile)

Login via Apple Sign-In for iOS apps.

POST /auth/apple/mobile

Request Body:

{
"identity_token": "eyJ...",
"user": "apple-user-id",
"full_name": {
"givenName": "John",
"familyName": "Doe"
}
}

Response: 200 OK (same format as Login)

Get Current User

Get authenticated user's profile.

GET /auth/me

Headers:

Authorization: Bearer <token>

Response: 200 OK

{
"id": "uuid",
"email": "user@example.com",
"username": "username",
"avatar_url": null,
"subscription_tier": "FREE",
"is_verified": true,
"is_active": true,
"created_at": "2025-01-01T00:00:00Z",
"last_login": "2025-01-15T10:00:00Z",
"oauth_provider": null,
"terms_accepted_at": "2025-01-01T00:00:00Z"
}

Refresh Token

Refresh access token using refresh token.

POST /auth/refresh

Request Body:

{
"refresh_token": "eyJ..."
}

Response: 200 OK

{
"access_token": "eyJ...",
"refresh_token": "eyJ...",
"token_type": "bearer"
}

Verify Email

Verify user's email address.

GET /auth/verify-email?token={verification_token}

Response: Redirects to app with success/error message.

Resend Verification Email

Resend email verification link.

POST /auth/resend-verification

Request Body:

{
"email": "user@example.com"
}

Response: 200 OK

Request Password Reset

Request a password reset email.

POST /auth/password-reset/request

Request Body:

{
"email": "user@example.com"
}

Response: 200 OK

Confirm Password Reset

Reset password using the token from email.

POST /auth/password-reset/confirm

Request Body:

{
"token": "reset-token-from-email",
"new_password": "new-strong-password"
}

Response: 200 OK

Change Password

Change password for authenticated user.

POST /auth/password-change

Headers:

Authorization: Bearer <token>

Request Body:

{
"current_password": "current-password",
"new_password": "new-strong-password"
}

Response: 200 OK

Accept Terms of Service

Accept or re-accept Terms of Service (for OAuth users or terms updates).

POST /auth/accept-terms

Headers:

Authorization: Bearer <token>

Request Body:

{
"accepted": true,
"consent_method": "web_checkbox"
}

Response: 200 OK

Get user's consent history for GDPR compliance.

GET /auth/consent-history

Headers:

Authorization: Bearer <token>

Response: 200 OK

{
"consents": [
{
"id": "uuid",
"consent_type": "tos",
"document_version": "1.0",
"accepted_at": "2025-01-01T00:00:00Z",
"consent_method": "web_checkbox",
"is_active": true
}
],
"total": 1
}

API Keys

List API Keys

Get all API keys for the authenticated user.

GET /api/keys

Headers:

Authorization: Bearer <token>

Response: 200 OK

[
{
"id": "uuid",
"name": "Production Server",
"key_prefix": "noti_abc",
"created_at": "2025-01-01T00:00:00Z",
"expires_at": null,
"last_used_at": "2025-01-15T10:00:00Z"
}
]

Create API Key

Create a new API key.

POST /api/keys

Headers:

Authorization: Bearer <token>
Content-Type: application/json

Request Body:

{
"name": "CI/CD Pipeline",
"expires_at": "2026-01-01T00:00:00Z"
}

Response: 201 Created

{
"id": "uuid",
"key": "noti_abc123...",
"name": "CI/CD Pipeline",
"created_at": "2025-01-15T10:30:00Z",
"expires_at": "2026-01-01T00:00:00Z"
}
Save the Key

The full key is only shown once. Save it securely!

Revoke API Key

Revoke an API key.

DELETE /api/keys/{key_id}

Headers:

Authorization: Bearer <token>

Response: 204 No Content


Topic Access Tokens

List Topic Tokens

Get all access tokens for a topic.

GET /api/topics/{topic}/access-tokens

Headers:

Authorization: Bearer <token>

Response: 200 OK

Create Topic Token

Create a new topic access token.

POST /api/topics/{topic}/access-tokens

Request Body:

{
"name": "External Service",
"permissions": ["read", "write"],
"expires_at": "2026-01-01T00:00:00Z"
}

Response: 201 Created

Revoke Topic Token

Revoke a topic access token.

DELETE /api/topics/{topic}/access-tokens/{token_id}

Response: 204 No Content


Teams

Teams require a TEAM+ subscription tier.

List Teams

Get all teams for the authenticated user.

GET /api/teams

Headers:

Authorization: Bearer <token>

Response: 200 OK

[
{
"id": "uuid",
"name": "engineering",
"display_name": "Engineering Team",
"description": "DevOps and Backend",
"owner_id": "uuid",
"member_count": 5,
"my_role": "owner",
"is_active": true,
"created_at": "2025-01-01T00:00:00Z",
"updated_at": "2025-01-15T10:00:00Z"
}
]

Get Team Stats

Get team statistics for current user (as owner).

GET /api/teams/stats

Headers:

Authorization: Bearer <token>

Response: 200 OK

{
"base_members": 5,
"additional_members": 0,
"used_members": 3,
"total_members": 5,
"available_members": 2,
"percentage_used": 60.0,
"daily_message_limit": 10000,
"message_retention_days": 30
}

List Deactivated Teams

List all deactivated teams owned by the current user.

GET /api/teams/deactivated

Headers:

Authorization: Bearer <token>

Response: 200 OK

Create Team

Create a new team (requires TEAM+ subscription).

POST /api/teams

Headers:

Authorization: Bearer <token>
Content-Type: application/json

Request Body:

{
"name": "engineering",
"display_name": "Engineering Team",
"description": "DevOps and Backend"
}

Response: 201 Created

Get Team Details

Get detailed team information (members only).

GET /api/teams/{team_id}

Headers:

Authorization: Bearer <token>

Response: 200 OK

{
"id": "uuid",
"name": "engineering",
"display_name": "Engineering Team",
"description": "DevOps and Backend",
"owner_id": "uuid",
"member_count": 5,
"is_active": true,
"created_at": "2025-01-01T00:00:00Z",
"updated_at": "2025-01-15T10:00:00Z",
"members": [
{
"id": "uuid",
"team_id": "uuid",
"user_id": "uuid",
"username": "john",
"email": "john@example.com",
"role": "owner",
"joined_at": "2025-01-01T00:00:00Z",
"is_active": true
}
],
"my_role": "owner"
}

Update Team

Update team details (admin or owner only).

PATCH /api/teams/{team_id}

Headers:

Authorization: Bearer <token>
Content-Type: application/json

Request Body:

{
"display_name": "Updated Team Name",
"description": "Updated description"
}

Response: 200 OK

Delete Team

Delete team (owner only).

DELETE /api/teams/{team_id}

Headers:

Authorization: Bearer <token>

Query Parameters:

  • delete_topics (bool, optional): If true, delete team topics. If false (default), convert to private topics.

Response: 204 No Content

Reactivate Team

Reactivate a deactivated team (owner only, requires TEAM+ tier).

POST /api/teams/{team_id}/reactivate

Headers:

Authorization: Bearer <token>

Response: 200 OK

List Team Members

List all team members (members only).

GET /api/teams/{team_id}/members

Headers:

Authorization: Bearer <token>

Response: 200 OK

Update Member Role

Update team member role (admin or owner only).

PATCH /api/teams/{team_id}/members/{user_id}

Headers:

Authorization: Bearer <token>
Content-Type: application/json

Request Body:

{
"role": "admin"
}

Response: 200 OK

Remove Team Member

Remove team member (admin or owner only, cannot remove owner).

DELETE /api/teams/{team_id}/members/{user_id}

Headers:

Authorization: Bearer <token>

Response: 204 No Content

Invite Team Member

Invite new team member (admin or owner only, requires active team).

POST /api/teams/{team_id}/invites

Headers:

Authorization: Bearer <token>
Content-Type: application/json

Request Body:

{
"email": "member@example.com",
"role": "member"
}

Response: 201 Created

{
"id": "uuid",
"team_id": "uuid",
"email": "member@example.com",
"role": "member",
"invited_by_id": "uuid",
"created_at": "2025-01-15T10:00:00Z",
"expires_at": "2025-01-22T10:00:00Z",
"is_expired": false
}

List Team Invites

List pending team invitations (admin or owner only).

GET /api/teams/{team_id}/invites

Headers:

Authorization: Bearer <token>

Response: 200 OK

Accept Team Invite

Accept team invitation.

POST /api/teams/invites/accept

Headers:

Authorization: Bearer <token>
Content-Type: application/json

Request Body:

{
"token": "invitation-token"
}

Response: 200 OK

Resend Team Invite

Resend team invitation email.

POST /api/teams/invites/{invite_id}/resend

Headers:

Authorization: Bearer <token>

Response: 204 No Content

Cancel Team Invite

Cancel team invitation.

DELETE /api/teams/invites/{invite_id}

Headers:

Authorization: Bearer <token>

Response: 204 No Content


Devices

Register Device

Register a mobile device for push notifications.

POST /api/devices/register

Headers:

Authorization: Bearer <token>
Content-Type: application/json

Request Body:

{
"push_token": "ExponentPushToken[xxx]",
"platform": "ios|android|expo",
"device_id": "unique-device-id",
"device_name": "iPhone 13 Pro",
"app_version": "1.0.0"
}

Response: 201 Created

{
"id": "uuid",
"user_id": "uuid",
"push_token": "ExponentPushToken[xxx]",
"platform": "ios",
"device_id": "unique-device-id",
"device_name": "iPhone 13 Pro",
"app_version": "1.0.0",
"is_active": true,
"created_at": "2025-01-15T10:00:00Z",
"last_seen": "2025-01-15T10:00:00Z"
}

List My Devices

Get all devices for current user.

GET /api/devices/my

Headers:

Authorization: Bearer <token>

Response: 200 OK

[
{
"id": "uuid",
"user_id": "uuid",
"push_token": "ExponentPushToken[xxx]",
"platform": "ios",
"device_id": "unique-device-id",
"device_name": "iPhone 13 Pro",
"app_version": "1.0.0",
"is_active": true,
"created_at": "2025-01-15T10:00:00Z",
"last_seen": "2025-01-15T10:00:00Z"
}
]

Get Device

Get device by ID.

GET /api/devices/{device_id}

Headers:

Authorization: Bearer <token>

Response: 200 OK

Update Device

Update device information.

PUT /api/devices/{device_id}

Headers:

Authorization: Bearer <token>
Content-Type: application/json

Request Body:

{
"push_token": "ExponentPushToken[new_token]",
"device_name": "New Device Name",
"app_version": "1.1.0"
}

Response: 200 OK

Delete Device

Delete device (stops push notifications).

DELETE /api/devices/{device_id}

Headers:

Authorization: Bearer <token>

Response: 204 No Content

Send Test Notification

Send test push notification to device.

POST /api/devices/{device_id}/test

Headers:

Authorization: Bearer <token>

Response: 200 OK

{
"message": "Test notification sent",
"device_id": "uuid"
}

Subscriptions

Unified subscription management for both web and mobile notifications.

List Subscriptions

Get all subscriptions for the current user.

GET /api/subscriptions

Headers:

Authorization: Bearer <token>

Response: 200 OK

{
"subscriptions": [
{
"id": "uuid",
"user_id": "uuid",
"topic_id": "uuid",
"topic_name": "server-alerts",
"topic_description": "Production server monitoring",
"access_level": "PRIVATE",
"team_id": null,
"icon_name": "server",
"icon_color": "red",
"created_at": "2025-01-01T00:00:00Z",
"last_viewed_at": "2025-01-15T10:00:00Z",
"last_notified_at": "2025-01-15T09:30:00Z",
"web_notifications_enabled": true,
"mobile_notifications_enabled": true,
"mobile_notification_settings": {
"priority_threshold": 5,
"sound_enabled": true,
"vibrate_enabled": true,
"tags_filter": [],
"notification_sound": "default"
},
"is_pinned": false,
"topic_last_message_at": "2025-01-15T10:30:00Z",
"unread_count": 5,
"message_count": 42,
"subscriber_count": 10
}
],
"total": 1
}

Create Subscription

Subscribe to a topic (unified web + mobile).

POST /api/subscriptions

Headers:

Authorization: Bearer <token>
Content-Type: application/json

Request Body:

{
"topic_name": "server-alerts",
"web_notifications_enabled": true,
"mobile_notifications_enabled": true,
"mobile_notification_settings": {
"priority_threshold": 3,
"sound_enabled": true,
"vibrate_enabled": true,
"tags_filter": ["urgent", "critical"],
"notification_sound": "alert"
}
}

Response: 201 Created

Update Subscription

Update subscription notification settings.

PATCH /api/subscriptions/{subscription_id}

Headers:

Authorization: Bearer <token>
Content-Type: application/json

Request Body:

{
"web_notifications_enabled": false,
"mobile_notifications_enabled": true,
"mobile_notification_settings": {
"priority_threshold": 2,
"sound_enabled": true,
"vibrate_enabled": false
},
"is_pinned": true
}

Response: 200 OK

Delete Subscription

Unsubscribe from a topic.

DELETE /api/subscriptions/{subscription_id}

Headers:

Authorization: Bearer <token>

Response: 204 No Content

Delete Subscription by Topic

Unsubscribe from a topic by name.

DELETE /api/subscriptions/by-topic/{topic_name}

Headers:

Authorization: Bearer <token>

Response: 204 No Content

Check Subscription

Check if user is subscribed to a topic.

GET /api/subscriptions/check/{topic_name}

Headers:

Authorization: Bearer <token>

Response: 200 OK

{
"subscribed": true,
"topic_name": "server-alerts"
}

User Management

Get Current User

Get current user profile information.

GET /api/users/me

Headers:

Authorization: Bearer <token>

Response: 200 OK

{
"id": "uuid",
"email": "user@example.com",
"username": "username",
"avatar_url": null,
"subscription_tier": "FREE",
"subscription_expires_at": null,
"is_active": true,
"is_verified": true,
"created_at": "2025-01-01T00:00:00Z",
"last_login": "2025-01-15T10:00:00Z"
}

Update Current User

Update current user profile.

PATCH /api/users/me

Headers:

Authorization: Bearer <token>
Content-Type: application/json

Request Body:

{
"username": "new-username",
"email": "new-email@example.com"
}
Email Change

Changing email will set is_verified to false and require email re-verification.

Response: 200 OK

Export User Data (GDPR)

Export all user data (GDPR Article 15 - Right to Access, Article 20 - Data Portability).

GET /api/users/me/data

Headers:

Authorization: Bearer <token>

Response: 200 OK (JSON file download)

{
"export_metadata": {
"exported_at": "2025-01-15T10:00:00Z",
"user_id": "uuid",
"data_categories": ["account", "topics", "messages", "devices", "subscriptions", "api_keys", "access_tokens"]
},
"account": {
"user_id": "uuid",
"email": "user@example.com",
"username": "username",
"subscription_tier": "FREE",
"created_at": "2025-01-01T00:00:00Z"
},
"topics": [...],
"messages": [...],
"devices": [...],
"api_keys": [...],
"topic_access_tokens": [...],
"subscriptions": [...],
"statistics": {
"total_topics": 5,
"total_messages": 150,
"total_devices": 2,
"total_subscriptions": 10,
"total_api_keys": 3,
"account_age_days": 14
}
}

Delete Current User (GDPR)

Delete current user account and all associated data (GDPR Article 17 - Right to Erasure).

DELETE /api/users/me

Headers:

Authorization: Bearer <token>
Content-Type: application/json

Request Body:

{
"password": "current-password"
}
Irreversible Action

This action is IRREVERSIBLE. All user data will be deleted including:

  • User account
  • All topics created by the user
  • All messages published by the user
  • All devices registered
  • All subscriptions
  • All API keys
  • All access tokens
OAuth Users

OAuth users (Google, Apple) cannot delete their account via this endpoint. Please contact support.

Response: 204 No Content


Error Responses

All error responses follow this format:

{
"detail": "Error message"
}

Common Status Codes

CodeMeaning
200Success
201Created
204No Content (successful deletion)
400Bad Request
401Unauthorized
403Forbidden
404Not Found
409Conflict
422Validation Error
429Rate Limit Exceeded
500Internal Server Error

Rate Limiting

See API Overview - Rate Limiting for details.


Next Steps


Interactive Documentation

For the most comprehensive and up-to-date API documentation, use the interactive Swagger UI:

https://app.notifer.io/docs

The interactive docs allow you to:

  • Try API calls directly from your browser
  • See all request/response schemas
  • View detailed parameter descriptions
  • Test authentication flows