API Reference

Complete REST API reference for Notifs. While we recommend using our official SDK, you can also integrate directly with our REST API.

Base URL

https://notifs.io/api

Authentication

API Key Authentication

Management endpoints (create webhook, get webhook) use API key authentication:

Authorization: ntf_live_your_api_key

API keys can be created in your dashboard. Keys start with ntf_live_ (production) or ntf_test_ (development).

Signature Authentication

The notification endpoint (POST /webhook/:webhookId) uses signature-based authentication instead of API keys. This ensures only your server can trigger notifications. See Send Notification for details.

Example Request

curl https://notifs.io/api/webhooks/your-webhook-id \
  -H "Authorization: ntf_live_your_api_key"

Rate Limits

Rate limits are enforced per API key:

| Plan | Rate Limit | Header | |------|------------|--------| | Free | 10 req/sec | X-RateLimit-Limit: 10 | | Pro | 100 req/sec | X-RateLimit-Limit: 100 | | Enterprise | Custom | X-RateLimit-Limit: <custom> |

Rate Limit Headers

All responses include rate limit information:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1640995200

Webhooks

Send Notification (Consumer Endpoint)

Send a notification through your webhook. This endpoint uses signature-based authentication (not API key) for security.

Endpoint: POST /webhook/:webhookId

Parameters:

  • webhookId (path, required): The webhook ID (UUID format)

Headers:

  • Content-Type: application/json (required)
  • X-Notifs-Signature: t=<timestamp>,v1=<hash> (required) - HMAC-SHA256 signature

Request Body:

Any valid JSON payload. Common fields used by services:

{
  "title": "Payment Received",
  "message": "You received a payment of $99.00",
  "data": {
    "user": "john@example.com",
    "amount": "$99.00",
    "orderId": "order_123"
  }
}

Response: 200 OK

{
  "message": "Webhook processed successfully",
  "notificationId": "550e8400-e29b-41d4-a716-446655440000",
  "servicesExecuted": true,
  "usageInfo": {
    "current": 5,
    "limit": 105,
    "inGracePeriod": false
  }
}

Error Responses:

| Status | Code | Description | |--------|------|-------------| | 401 | invalid_signature | Invalid or missing signature | | 402 | quota_exceeded | Usage limit exceeded | | 409 | replay_attack_detected | Duplicate request within 5 minutes | | 429 | webhook_rate_limit | Rate limit exceeded |

Example (using SDK - recommended):

import { Notifs } from '@notifs/sdk'

const notifs = new Notifs({ apiKey: process.env.NOTIFS_API_KEY })
const webhook = await notifs.webhooks.get('your_webhook_id')

await webhook.send({
  title: 'Payment Received',
  message: 'You received a payment of $99.00',
  data: { user: 'john@example.com', amount: '$99.00' }
})

Note: We strongly recommend using the SDK which handles signature generation automatically. For manual signature generation, see the Security documentation.

Get Webhook

Retrieve webhook configuration and secret.

Endpoint: GET /webhooks/:webhookId

Authentication: API key or session

Response: 200 OK

{
  "success": true,
  "webhook": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Payment Notifications",
    "project_id": "project_abc123",
    "user_id": "user_xyz",
    "webhook_secret": "your-webhook-secret-uuid",
    "created_at": "2024-01-01T00:00:00.000Z",
    "updated_at": "2024-01-01T00:00:00.000Z"
  }
}

Example:

curl https://notifs.io/api/webhooks/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: ntf_live_your_api_key"

List Webhooks

Coming Soon: This endpoint is not yet available via the REST API. Webhooks can be listed via the dashboard or using the SDK's webhooks.list() method.

Create Webhook

Create a new webhook.

Endpoint: POST /webhooks

Authentication: API key or session

Request Body:

{
  "name": "Payment Notifications",
  "projectId": "optional-project-uuid"
}

| Field | Type | Required | Description | |-------|------|----------|-------------| | name | string | No | Webhook name (defaults to "New Webhook") | | projectId | string | No | Associate with a project |

Response: 200 OK

{
  "success": true,
  "webhook": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Payment Notifications",
    "project_id": null,
    "user_id": "user_xyz",
    "webhook_secret": "your-new-webhook-secret",
    "created_at": "2024-01-01T00:00:00.000Z",
    "updated_at": "2024-01-01T00:00:00.000Z"
  }
}

Example:

curl -X POST https://notifs.io/api/webhooks \
  -H "Authorization: ntf_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"name": "Order Notifications"}'

Note: Store the webhook_secret securely. It's used to sign requests when sending notifications.

Update Webhook

Coming Soon: Update endpoint is not yet available via the REST API. Webhooks can be updated via the dashboard.

Delete Webhook

Coming Soon: Delete endpoint is not yet available via the REST API. Webhooks can be deleted via the dashboard.

Regenerate Secret

Regenerate the webhook secret. This immediately invalidates the old secret.

Endpoint: POST /webhooks/:webhookId/regenerate-secret

Authentication: Session only (dashboard)

Response: 200 OK

{
  "success": true,
  "data": {
    "webhook_secret": "new-webhook-secret-here"
  }
}

Test Webhook

Send a test notification through your webhook to verify it's configured correctly.

Endpoint: POST /webhooks/:webhookId/test

Authentication: Session only (dashboard)

Response: 200 OK

{
  "success": true,
  "status": 200,
  "data": {
    "message": "Webhook processed successfully",
    "notificationId": "550e8400-e29b-41d4-a716-446655440000"
  }
}

Logs

Get Webhook Logs

Retrieve request logs for a specific webhook.

Endpoint: GET /webhooks/:webhookId/logs

Authentication: Session only (dashboard)

Query Parameters: | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | limit | number | 50 | Number of results to return | | offset | number | 0 | Pagination offset | | status | string | - | Filter by status: success or error |

Response: 200 OK

{
  "success": true,
  "data": {
    "logs": [
      {
        "id": "log-uuid",
        "webhook_id": "webhook-uuid",
        "request_body": { "title": "Test", "data": {} },
        "response_status": 200,
        "response_body": { "message": "Webhook processed successfully" },
        "signature_provided": "t=1234567890,v1=abc123...",
        "signature_valid": true,
        "duration_ms": 125,
        "created_at": "2024-01-01T00:00:00.000Z"
      }
    ],
    "total": 1,
    "limit": 50,
    "offset": 0
  }
}

Example:

curl "https://notifs.io/api/webhooks/550e8400-e29b-41d4-a716-446655440000/logs?limit=20&status=error" \
  -H "Cookie: your-session-cookie"

Note: Logs are only accessible via authenticated dashboard sessions, not API keys.

Channels

Notification channels are currently configured via the dashboard. API endpoints for channel configuration are coming soon.

Available Channels

| Channel | Configuration | |---------|---------------| | Email | Recipient email address and subject line | | SMS | Phone number (E.164 format, e.g. +14155551234) | | Slack | OAuth connection + channel selection (up to 3 channels) |

Error Handling

Management API Errors

Management endpoints (create, get, etc.) return errors in this format:

{
  "success": false,
  "error": {
    "code": "AUTH_1004",
    "message": "You must be logged in or provide a valid API key"
  }
}

Webhook Consumer Errors

The notification endpoint (POST /webhook/:webhookId) returns errors like:

{
  "message": "Invalid webhook signature",
  "code": "WEBHOOK_2001",
  "reason": "Signature timestamp too old"
}

Error Codes

| Code | Status | Description | |------|--------|-------------| | AUTH_1004 | 401 | Unauthorized - invalid or missing credentials | | WEBHOOK_2001 | 401 | Invalid signature | | WEBHOOK_2002 | 400 | Payload validation failed | | WEBHOOK_2003 | 404 | Webhook not found | | WEBHOOK_2005 | 409 | Replay attack detected (duplicate request) | | WEBHOOK_2006 | 429 | Webhook rate limit exceeded | | WEBHOOK_2009 | 413 | Payload too large (max 1MB) | | SUBSCRIPTION_6005 | 402 | Usage quota exceeded | | RATE_LIMIT_7003 | 429 | Rate limit exceeded | | VALIDATION_5001 | 400 | Invalid input | | DB_4004 | 404 | Resource not found | | SYSTEM_8001 | 500 | Internal server error |

Rate Limit Error Response

{
  "message": "Rate limit exceeded",
  "code": "RATE_LIMIT_7003",
  "retryAfter": 60
}

Headers included:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1640995200

Replay Protection

Duplicate requests with identical payloads are automatically rejected within a 5-minute window. This prevents accidental duplicate notifications from network retries or application bugs.

If a duplicate is detected, you'll receive:

{
  "message": "Duplicate request detected",
  "code": "WEBHOOK_2005",
  "fingerprint": "abc123...",
  "info": "This request was already processed within the last 5 minutes"
}

Status: 409 Conflict

To send the same payload again, wait 5 minutes or modify the payload slightly (e.g., add a timestamp).

Webhook Signatures

When sending notifications via POST /webhook/:webhookId, you must include a signature header:

X-Notifs-Signature: t=<unix_timestamp>,v1=<hmac_sha256_hex>

The signature is computed as:

HMAC-SHA256(webhook_secret, "<timestamp>.<json_payload>")

Important:

  • Timestamps must be within 5 minutes of the server time
  • The SDK handles signature generation automatically
  • See the Security documentation for manual implementation details

Pagination

Endpoints that return lists (like webhook logs) support offset-based pagination:

# First page
curl "https://notifs.io/api/webhooks/webhook-id/logs?limit=50" \
  -H "Cookie: your-session-cookie"

# Next page
curl "https://notifs.io/api/webhooks/webhook-id/logs?limit=50&offset=50" \
  -H "Cookie: your-session-cookie"

Response includes pagination metadata:

{
  "success": true,
  "data": {
    "logs": [...],
    "total": 150,
    "limit": 50,
    "offset": 0
  }
}

Stability

The API is designed for stability. We avoid breaking changes whenever possible, and will communicate any necessary changes well in advance.

SDKs

We recommend using our official SDKs instead of calling the REST API directly:

Support

Next Steps