Skip to content

Topic Access Tokens

Topic access tokens provide scoped authentication for publishing to specific private topics.

API Keys vs Topic Access Tokens

Confused about which to use?

  • Topic Access Tokens (tk_...) - Scoped to one topic, recommended for scripts and integrations
  • User API Keys (noti_...) - Work across all your topics, for broader automation

👉 Learn more about the differences

Overview

Why use topic access tokens?

  • Topic-scoped - Works only for a specific topic
  • Secure - Limited permissions (publish-only or subscribe-only)
  • Shareable - Safe to share with external services
  • Revocable - Revoke without affecting other integrations
  • Trackable - Monitor usage per token

Perfect for:

  • CI/CD pipelines notifying a single topic
  • Third-party integrations (monitoring tools, webhooks)
  • Sharing topic access with teammates without sharing account credentials
  • Automated scripts that publish to one topic

Creating Topic Access Tokens

Via Web Dashboard

  1. Go to your topic page (e.g., app.notifer.io/topic/my-topic)
  2. Click Topic Settings (gear icon)
  3. Navigate to Access Tokens tab
  4. Click Create Token
  5. Enter token name (e.g., "CI Pipeline")
  6. Select permissions: publish, subscribe, or both
  7. Click Create
  8. Copy the token (shown only once!)

Via API

# Create a publish-only token
curl -X POST https://app.notifer.io/api/topics/my-topic/access-tokens \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "CI Pipeline Token",
    "permissions": ["publish"]
  }'

Response:

{
  "id": "token_abc123",
  "token": "tk_FjZTOcx14k4_Kg6RtUCikAPYc2KNjXIMkWQUvDSREFc",
  "name": "CI Pipeline Token",
  "topic": "my-topic",
  "permissions": ["publish"],
  "created_at": "2025-11-10T10:00:00Z",
  "last_used_at": null
}

Save Your Token

The token is shown only once during creation. Save it securely! If you lose it, you'll need to create a new token.

Using Topic Access Tokens

Use the X-Topic-Token header:

curl -d "Build completed successfully" \
  -H "X-Topic-Token: tk_FjZTOcx14k4_Kg6RtUCikAPYc2KNjXIMkWQUvDSREFc" \
  -H "X-Title: CI/CD" \
  -H "X-Priority: 3" \
  https://app.notifer.io/my-topic

As Query Parameter

For tools that don't support custom headers:

curl -d "Build completed" \
  "https://app.notifer.io/my-topic?token=tk_FjZTOcx14k4_Kg6RtUCikAPYc2KNjXIMkWQUvDSREFc"

In Python

import requests

TOKEN = "tk_FjZTOcx14k4_Kg6RtUCikAPYc2KNjXIMkWQUvDSREFc"

response = requests.post(
    "https://app.notifer.io/my-topic",
    data="Build completed",
    headers={
        "X-Topic-Token": TOKEN,
        "X-Title": "CI/CD",
        "X-Priority": "3"
    }
)

In JavaScript

const TOKEN = 'tk_FjZTOcx14k4_Kg6RtUCikAPYc2KNjXIMkWQUvDSREFc';

fetch('https://app.notifer.io/my-topic', {
  method: 'POST',
  headers: {
    'X-Topic-Token': TOKEN,
    'X-Title': 'CI/CD',
    'Content-Type': 'text/plain'
  },
  body: 'Build completed'
});

Token Permissions

Control what each token can do:

Permission Description Use Case
publish Publish messages to the topic CI/CD notifications, monitoring alerts
subscribe Subscribe to topic messages Log aggregation, webhooks
publish,subscribe Both publish and subscribe Full integration access

Permission Examples

# CI/CD pipeline - only needs to send notifications
curl -X POST https://app.notifer.io/api/topics/deployments/access-tokens \
  -H "Authorization: Bearer YOUR_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "GitHub Actions",
    "permissions": ["publish"]
  }'
# External service consuming messages
curl -X POST https://app.notifer.io/api/topics/events/access-tokens \
  -H "Authorization: Bearer YOUR_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Log Aggregator",
    "permissions": ["subscribe"]
  }'
# Full integration access
curl -X POST https://app.notifer.io/api/topics/monitoring/access-tokens \
  -H "Authorization: Bearer YOUR_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Monitoring Service",
    "permissions": ["publish", "subscribe"]
  }'

Token Management

List Tokens for a Topic

curl https://app.notifer.io/api/topics/my-topic/access-tokens \
  -H "Authorization: Bearer YOUR_JWT"

Revoke a Token

curl -X DELETE https://app.notifer.io/api/topics/my-topic/access-tokens/token_abc123 \
  -H "Authorization: Bearer YOUR_JWT"

After revocation:

  • Token immediately stops working
  • All requests with this token return 401 Unauthorized
  • Token cannot be re-enabled (create a new one instead)

Monitor Token Usage

View in topic settings:

  • Last used - When the token was last used
  • Total requests - Number of requests made with this token
  • Created by - User who created the token

Comparison with API Keys

Understanding when to use each authentication method:

Feature Topic Access Token (tk_...) User API Key (noti_...)
Scope Single topic only All your topics
Prefix tk_... noti_...
Header X-Topic-Token X-API-Key
Permissions Per-token (publish/subscribe) Global scopes
Best for Topic-specific integrations Multi-topic automation
Sharing ✅ Safe (limited scope) ❌ Risky (full access)
Revocation impact Only affects one topic Affects all integrations
Created via Topic settings Account settings
Example use CI/CD for one topic Admin scripts, dashboards

When to Use Topic Access Tokens

Use topic access tokens when:

  • Integrating with external services (GitHub Actions, monitoring tools)
  • Each integration should only access one topic
  • You want to share access without sharing account credentials
  • You need fine-grained permission control per topic
  • You want to easily revoke access for one integration

When to Use API Keys

Use API keys when:

  • Building automation that works across multiple topics
  • Creating admin scripts or dashboards
  • You control the entire integration
  • You need topic management permissions (create, delete topics)

Security Best Practices

Storage

Do:

  • Store tokens in environment variables
  • Use CI/CD secret storage (GitHub Secrets, GitLab CI Variables)
  • Use secret managers (AWS Secrets Manager, HashiCorp Vault)
  • Create separate tokens for each integration
  • Revoke unused tokens

Don't:

  • Commit tokens to version control
  • Share tokens in plain text (email, Slack)
  • Use the same token across multiple services
  • Grant more permissions than needed (e.g., publish+subscribe when only publish is needed)

Environment Variables

# Store in .env file (add to .gitignore!)
NOTIFER_TOPIC_TOKEN=tk_FjZTOcx14k4_Kg6RtUCikAPYc2KNjXIMkWQUvDSREFc

# Load in script
source .env
curl -H "X-Topic-Token: $NOTIFER_TOPIC_TOKEN" \
  -d "Message" \
  https://app.notifer.io/my-topic

GitHub Actions

# Store token in repository secrets
- name: Notify deployment
  run: |
    curl -d "Deploy completed" \
      -H "X-Topic-Token: ${{ secrets.NOTIFER_TOPIC_TOKEN }}" \
      -H "X-Title: Deployment" \
      https://app.notifer.io/deployments

Docker Secrets

# Create secret
echo "tk_..." | docker secret create notifer_token -

# Use in docker-compose.yml
services:
  app:
    secrets:
      - notifer_token
    environment:
      NOTIFER_TOKEN_FILE: /run/secrets/notifer_token

secrets:
  notifer_token:
    external: true

Real-World Examples

GitHub Actions CI/CD

name: Deploy and Notify

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy
        run: ./deploy.sh

      - name: Notify success
        if: success()
        run: |
          curl -d "Deployment to production succeeded ✅" \
            -H "X-Topic-Token: ${{ secrets.NOTIFER_TOPIC_TOKEN }}" \
            -H "X-Title: Deploy Success" \
            -H "X-Priority: 3" \
            -H "X-Tags: ci,deploy,success" \
            https://app.notifer.io/deployments

      - name: Notify failure
        if: failure()
        run: |
          curl -d "Deployment to production failed ❌" \
            -H "X-Topic-Token: ${{ secrets.NOTIFER_TOPIC_TOKEN }}" \
            -H "X-Title: Deploy Failed" \
            -H "X-Priority: 5" \
            -H "X-Tags: ci,deploy,error" \
            https://app.notifer.io/deployments

Server Monitoring Script

#!/bin/bash

TOPIC_TOKEN="tk_FjZTOcx14k4_Kg6RtUCikAPYc2KNjXIMkWQUvDSREFc"
TOPIC="server-alerts"

# Check disk space
USAGE=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//')

if [ "$USAGE" -gt 90 ]; then
  PRIORITY=5
  MESSAGE="🚨 CRITICAL: Disk usage at ${USAGE}%"
elif [ "$USAGE" -gt 80 ]; then
  PRIORITY=4
  MESSAGE="⚠️ WARNING: Disk usage at ${USAGE}%"
else
  exit 0
fi

curl -d "$MESSAGE" \
  -H "X-Topic-Token: $TOPIC_TOKEN" \
  -H "X-Priority: $PRIORITY" \
  -H "X-Tags: server,disk,monitoring" \
  "https://app.notifer.io/$TOPIC"

Database Backup Notification

#!/bin/bash

TOKEN="tk_your_token_here"
TOPIC="backups"

# Perform backup
if pg_dump production_db > /backups/db_$(date +%Y%m%d).sql; then
  # Success notification
  curl -d "Database backup completed: $(date)" \
    -H "X-Topic-Token: $TOKEN" \
    -H "X-Title: Backup Success" \
    -H "X-Priority: 3" \
    -H "X-Tags: database,backup,success" \
    "https://app.notifer.io/$TOPIC"
else
  # Failure notification
  curl -d "Database backup FAILED: $(date)" \
    -H "X-Topic-Token: $TOKEN" \
    -H "X-Title: Backup Failed" \
    -H "X-Priority: 5" \
    -H "X-Tags: database,backup,error" \
    "https://app.notifer.io/$TOPIC"
fi

Troubleshooting

401 Unauthorized

Cause: Invalid or missing token

Solution:

  • Verify token is correct (no extra spaces or newlines)
  • Check token hasn't been revoked
  • Ensure using correct header: X-Topic-Token (not X-API-Key)
  • Confirm token is for the correct topic

403 Forbidden

Cause: Token lacks required permission

Solution:

  • Check token has publish permission for POST/PUT requests
  • Check token has subscribe permission for SSE/WebSocket connections
  • Verify topic is still private (token only works for private topics)

Token Shows as Never Used

Cause: Token not being sent correctly

Solution:

  • Check header name: X-Topic-Token (case-sensitive)
  • Verify nginx is passing through the header (see nginx config)
  • Test with curl verbosely: curl -v ...

Nginx Configuration

If running your own nginx proxy, ensure it passes through the X-Topic-Token header:

location ~ ^/[a-zA-Z0-9_-]+$ {
    proxy_pass http://backend:8000;

    # Required: Pass through authentication headers
    proxy_set_header X-Topic-Token $http_x_topic_token;
    proxy_set_header Authorization $http_authorization;

    # Also pass through message headers
    proxy_set_header X-Title $http_x_title;
    proxy_set_header X-Priority $http_x_priority;
    proxy_set_header X-Tags $http_x_tags;
}

Next Steps