API Reference

Complete reference for all StackForDevs API endpoints with request/response schemas.

Base URLs:
Authentication: https://auth.stackfordevs.com
Billing: https://billing.stackfordevs.com
CMS: https://cms.stackfordevs.com
LLM: https://llm.stackfordevs.com
Mailer: https://mailer.stackfordevs.com
Notifications: https://notifications.stackfordevs.com

Authentication

All requests require authentication headers:

x-api-key: YOUR_PUBLIC_KEY
x-secret-key: YOUR_SECRET_KEY
x-tenant-id: YOUR_TENANT_ID
x-project-id: YOUR_PROJECT_ID
Content-Type: application/json

Some endpoints also require a Bearer token for user-specific operations:

Authorization: Bearer YOUR_ACCESS_TOKEN

Authentication Service

User registration, authentication, password reset, email verification, and profile management.

POST /v1/register

Register a new user account.

Request Body

{
  "email": "user@example.com",         // required, string (email format)
  "password": "SecurePass123!",        // required, string
  "metadata": {                        // optional, object
    "firstName": "John",
    "lastName": "Doe",
    "company": "Acme Inc"
  }
}

Response 201 Created

{
  "user": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "user@example.com",
    "createdAt": "2025-01-15T10:30:00Z"
  }
}

Error Responses

// 400 Bad Request - Invalid payload
// 409 Conflict - Email already registered
POST /v1/login

Authenticate with email and password.

Request Body

{
  "email": "user@example.com",         // required, string (email format)
  "password": "SecurePass123!"         // required, string
}

Response 200 OK

{
  "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "user": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "user@example.com"
  }
}

Error Responses

// 400 Bad Request - Missing credentials or tenant identifier
// 401 Unauthorized - Invalid credentials
// 423 Locked - Account locked
POST /v1/refresh-token

Exchange a refresh token for new session tokens.

Request Body

{
  "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Response 200 OK

{
  "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Error Responses

// 400 Bad Request - Missing token
// 401 Unauthorized - Invalid refresh token
POST /v1/logout

Revoke all sessions for the authenticated user. Invalidates all refresh tokens by incrementing the token version.

Request Body

{
  "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Response 200 OK

{
  "message": "Logged out successfully"
}
POST /v1/forgot-password

Request a password reset email.

Request Body

{
  "email": "user@example.com"          // required, string (email format)
}

Response 200 OK

{
  "message": "Reset request accepted"
}
POST /v1/reset-password

Reset a password using a reset token.

Request Body

{
  "token": "reset_token_here",         // required, string
  "password": "NewSecurePass123!"      // required, string
}

Response 200 OK

{
  "message": "Password reset successful"
}

Error Responses

// 400 Bad Request - Invalid token or payload
// 410 Gone - Token expired
POST /v1/verify-email

Verify email address with token.

Request Body

{
  "token": "verification_token_here"   // required, string
}

Response 200 OK

{
  "message": "Email verified successfully"
}

Error Responses

// 400 Bad Request - Invalid or expired token
POST /v1/resend-verification

Resend email verification.

Request Body

{
  "email": "user@example.com"          // required, string (email format)
}

Response 200 OK

{
  "message": "Verification email sent"
}

Error Responses

// 400 Bad Request - Email not found or already verified
GET /v1/me

Get current user profile. Requires Bearer token authentication.

Headers

Authorization: Bearer YOUR_ACCESS_TOKEN

Response 200 OK

{
  "user": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "user@example.com",
    "emailVerified": true,
    "phoneNumber": "+1234567890",
    "phoneVerified": false,
    "avatarUrl": "https://example.com/avatar.jpg",
    "username": "johndoe",
    "metadata": {
      "firstName": "John",
      "lastName": "Doe"
    },
    "createdAt": "2025-01-15T10:30:00Z"
  }
}

Error Responses

// 401 Unauthorized - Missing or invalid token
PATCH /v1/me

Update current user profile. Requires Bearer token authentication.

Headers

Authorization: Bearer YOUR_ACCESS_TOKEN

Request Body

{
  "phoneNumber": "+1234567890",        // optional, string
  "avatarUrl": "https://...",          // optional, string
  "username": "johndoe",               // optional, string
  "metadata": {                        // optional, object
    "firstName": "John",
    "lastName": "Doe"
  }
}

Response 200 OK

{
  "user": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "user@example.com",
    "phoneNumber": "+1234567890",
    "avatarUrl": "https://...",
    "username": "johndoe",
    "metadata": { ... },
    "updatedAt": "2025-01-15T11:00:00Z"
  }
}
GET /v1/lookup/email

Lookup customer details by email address. Requires API key authentication.

Query Parameters

email required string Email address to lookup

Response 200 OK

{
  "user": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "user@example.com",
    "tenantId": "tenant_123",
    "projectId": "project_456",
    "isAdmin": false,
    "isCoreAccount": false,
    "emailVerified": true,
    "phoneNumber": "+1234567890",
    "phoneVerified": false,
    "avatarUrl": "https://...",
    "username": "johndoe",
    "metadata": { ... },
    "lastLogin": "2025-01-15T10:30:00Z",
    "createdAt": "2025-01-14T09:00:00Z"
  }
}

Error Responses

// 400 Bad Request - Missing email parameter
// 401 Unauthorized - Invalid API keys
// 404 Not Found - User not found

Billing Service

Stripe checkout sessions, customer portal, payment intents, subscriptions, and advanced Stripe configuration.

POST /v1/stripe/checkout/session

Create a Stripe Checkout Session for hosted payment. Requires both JWT (to identify the buyer) and API keys (to identify the tenant's Stripe account).

Headers

Authorization: Bearer YOUR_ACCESS_TOKEN
x-api-key: YOUR_PUBLIC_KEY
x-secret-key: YOUR_SECRET_KEY
x-tenant-id: YOUR_TENANT_ID
x-project-id: YOUR_PROJECT_ID

Query Parameters

environment optional string "test" or "live" (default: "test")

Request Body

{
  "line_items": [                      // required, array
    {
      "price": "price_1234567890",     // Stripe Price ID
      "quantity": 1
    }
  ],
  "mode": "subscription",              // required: "payment", "subscription", or "setup"
  "success_url": "https://...",        // required, string
  "cancel_url": "https://...",         // required, string
  "customer_email": "user@example.com", // optional, string
  "metadata": { ... },                 // optional, object
  "allow_promotion_codes": true,       // optional, boolean
  "billing_address_collection": "auto" // optional: "auto" or "required"
}

Response 201 Created

{
  "success": true,
  "session": {
    "id": "cs_test_...",
    "url": "https://checkout.stripe.com/c/pay/cs_test_...",
    "customer": "cus_...",
    "mode": "subscription"
  }
}

Error Responses

// 400 Bad Request - Invalid request
// 401 Unauthorized - Missing or invalid authentication
GET /v1/stripe/checkout/session/:sessionId

Get Checkout Session status.

Headers

Authorization: Bearer YOUR_ACCESS_TOKEN
x-api-key: YOUR_PUBLIC_KEY
x-secret-key: YOUR_SECRET_KEY
x-tenant-id: YOUR_TENANT_ID
x-project-id: YOUR_PROJECT_ID

Response 200 OK

{
  "session": {
    "id": "cs_test_...",
    "status": "complete",
    "payment_status": "paid"
  }
}

Error Responses

// 401 Unauthorized - Missing or invalid authentication
// 404 Not Found - Session not found
POST /v1/stripe/customer-portal/session

Create a Stripe Customer Portal session for customers to manage their billing and subscription.

Headers

Authorization: Bearer YOUR_ACCESS_TOKEN
x-api-key: YOUR_PUBLIC_KEY
x-secret-key: YOUR_SECRET_KEY
x-tenant-id: YOUR_TENANT_ID
x-project-id: YOUR_PROJECT_ID

Request Body

{
  "customer": "cus_123456789",         // required, Stripe Customer ID
  "return_url": "https://example.com/account" // required, string
}

Response 201 Created

{
  "success": true,
  "session": {
    "id": "bps_...",
    "url": "https://billing.stripe.com/p/session/...",
    "customer": "cus_...",
    "return_url": "https://..."
  }
}
POST /v1/stripe/payment/intent

Create a Stripe Payment Intent for direct card integration.

Request Body

{
  "amount": 2000,                      // required, number (in cents)
  "currency": "usd",                   // required, string (ISO currency code)
  "customer": "cus_123456789",         // optional, Stripe Customer ID
  "description": "Order #12345",       // optional, string
  "metadata": { ... },                 // optional, object
  "payment_method_types": ["card"],    // optional, array
  "receipt_email": "user@example.com", // optional, string
  "setup_future_usage": "off_session"  // optional: "on_session" or "off_session"
}

Response 201 Created

{
  "paymentIntent": {
    "id": "pi_...",
    "client_secret": "pi_..._secret_...",
    "status": "requires_payment_method",
    "amount": 2000,
    "currency": "usd"
  }
}
GET /v1/stripe/payment/intent/:paymentIntentId

Get Payment Intent status.

Response 200 OK

{
  "paymentIntent": {
    "id": "pi_...",
    "status": "succeeded",
    "amount": 2000,
    "currency": "usd"
  }
}

Error Responses

// 401 Unauthorized - Missing or invalid authentication
// 404 Not Found - Payment intent not found
GET /v1/customer/subscription

Check a customer's subscription status by email.

Query Parameters

customerEmail required string The email address of the customer to check
environment optional string "test" or "live" (default: "test")

Response 200 OK

{
  "subscription": {
    "id": "sub_...",
    "tenantId": "tenant_123",
    "planId": "price_...",
    "status": "active",
    "currentPeriodEnd": "2025-02-15T10:30:00Z",
    "stripeSubscriptionId": "sub_...",
    "cancelAtPeriodEnd": false,
    "canceledAt": null,
    "plan": {
      "name": "Professional"
    }
  }
}

Error Responses

// 400 Bad Request - Invalid request (missing customerEmail)
// 401 Unauthorized - Missing or invalid API keys
// 500 Internal Server Error
GET /v1/stripe/account/status

Get Stripe account status and readiness.

Query Parameters

environment optional string "test" or "live" (default: "live")

Response 200 OK

{
  "configured": true,
  "ready": true,
  "account": {
    "id": "acct_...",
    "email": "billing@example.com",
    "country": "US",
    "default_currency": "usd",
    "charges_enabled": true,
    "payouts_enabled": true,
    "details_submitted": true,
    "type": "standard"
  },
  "requirements": {
    "currently_due": [],
    "eventually_due": [],
    "past_due": [],
    "disabled_reason": null
  },
  "issues": [],
  "environment": "live"
}

CMS Service

Content management (blog posts, FAQs, pages, custom types), custom content type definitions, and public news aggregation.

POST /v1/content

Create a new content item.

Request Body

{
  "type": "blog",                      // required: "blog", "faq", "page", or "custom"
  "title": "My Blog Post",             // required, string
  "slug": "my-blog-post",              // optional, string (auto-generated if not provided)
  "content": "Post content here...",   // required, string
  "metadata": {                        // optional, object
    "author": "John Doe",
    "tags": ["tutorial", "getting-started"]
  },
  "status": "published"                // optional: "draft", "published", "archived"
}

Response 201 Created

{
  "id": "cnt_abc123xyz",
  "tenantId": "tenant_123",
  "projectId": "project_456",
  "type": "blog",
  "title": "My Blog Post",
  "slug": "my-blog-post",
  "content": "Post content here...",
  "status": "published",
  "createdAt": "2025-01-15T10:30:00Z",
  "updatedAt": "2025-01-15T10:30:00Z"
}

Error Responses

// 400 Bad Request - Invalid request
// 401 Unauthorized
GET /v1/content

Get all content items with optional filtering.

Query Parameters

type optional string Filter by content type
status optional string Filter by status
limit optional integer Number of items to return (default: 20)
offset optional integer Pagination offset (default: 0)

Response 200 OK

{
  "content": [
    {
      "id": "cnt_abc123",
      "type": "blog",
      "title": "My Blog Post",
      "slug": "my-blog-post",
      "status": "published",
      "createdAt": "2025-01-15T10:30:00Z"
    }
  ],
  "total": 42,
  "limit": 20,
  "offset": 0
}
GET /v1/content/:id

Get content by ID.

Response 200 OK

{
  "id": "cnt_abc123xyz",
  "type": "blog",
  "title": "My Blog Post",
  "slug": "my-blog-post",
  "content": "Post content here...",
  "status": "published",
  "metadata": { ... },
  "createdAt": "2025-01-15T10:30:00Z",
  "updatedAt": "2025-01-15T10:30:00Z"
}

Error Responses

// 404 Not Found - Content not found
PUT /v1/content/:id

Update content.

Request Body

{
  "title": "Updated Title",            // optional, string
  "content": "Updated content...",     // optional, string
  "metadata": { ... },                 // optional, object
  "status": "published"                // optional, string
}

Response 200 OK

{
  "id": "cnt_abc123",
  "title": "Updated Title",
  "content": "Updated content...",
  "status": "published",
  "updatedAt": "2025-01-15T11:00:00Z"
}

Error Responses

// 404 Not Found - Content not found
DELETE /v1/content/:id

Delete content.

Response 204 No Content

No response body. Content deleted successfully.

Error Responses

// 404 Not Found - Content not found
POST /v1/content-types

Define a new custom content type with JSON schema.

Request Body

{
  "name": "Product",                   // required, string
  "description": "E-commerce product", // optional, string
  "schema": {                          // required, JSON Schema object
    "type": "object",
    "properties": {
      "price": { "type": "number" },
      "sku": { "type": "string" },
      "inStock": { "type": "boolean" }
    },
    "required": ["price", "sku"]
  }
}

Response 201 Created

{
  "id": "ctype_xyz789",
  "name": "Product",
  "description": "E-commerce product",
  "schema": { ... },
  "createdAt": "2025-01-15T10:30:00Z"
}

Error Responses

// 400 Bad Request - Invalid request
GET /v1/content-types

List all content types.

Response 200 OK

{
  "contentTypes": [
    {
      "id": "ctype_xyz789",
      "name": "Product",
      "description": "E-commerce product",
      "createdAt": "2025-01-15T10:30:00Z"
    }
  ]
}
GET /v1/news

Retrieve pre-fetched public news content (updated every 2 hours).

Query Parameters

category optional string Filter by news category
limit optional integer Number of items to return (default: 10)

Response 200 OK

{
  "news": [
    {
      "id": "news_abc123",
      "title": "Breaking News",
      "description": "Latest developments...",
      "url": "https://...",
      "publishedAt": "2025-01-15T09:00:00Z",
      "source": "News Source"
    }
  ]
}

Error Responses

// 401 Unauthorized

LLM Service

Text completion endpoints, batch processing for bulk operations, multi-provider support (OpenAI, Anthropic), provider credential management, and usage logs.

POST /v1/completions

Generate text completions using configured LLM providers (OpenAI, Anthropic). The provider is selected based on the model specified in the request.

Request Body

{
  "model": "gpt-4",                    // required, string (e.g., "gpt-4", "claude-3-opus")
  "messages": [                        // required, array
    {
      "role": "system",
      "content": "You are a helpful assistant."
    },
    {
      "role": "user",
      "content": "Explain quantum computing"
    }
  ],
  "max_tokens": 1000,                  // optional, integer (default varies by model)
  "temperature": 0.7                   // optional, number 0-2 (default: 1.0)
}

Response 200 OK

{
  "id": "comp_abc123xyz",
  "completion": "Quantum computing is a type of computing that...",
  "model": "gpt-4",
  "provider": "openai",
  "usage": {
    "prompt_tokens": 25,
    "completion_tokens": 245,
    "total_tokens": 270
  },
  "createdAt": "2025-01-15T10:30:00Z"
}

Error Responses

// 400 Bad Request - Invalid request
// 401 Unauthorized - Invalid API keys
// 500 Internal Server Error - Provider error
POST /v1/batch

Submit multiple completion requests for batch processing. Batch jobs are processed asynchronously and can save up to 50% on costs.

Request Body

{
  "requests": [                        // required, array
    {
      "custom_id": "request-1",
      "model": "gpt-4",
      "messages": [
        {
          "role": "user",
          "content": "Translate to Spanish: Hello"
        }
      ]
    },
    {
      "custom_id": "request-2",
      "model": "gpt-4",
      "messages": [
        {
          "role": "user",
          "content": "What is 2+2?"
        }
      ]
    }
  ],
  "webhook_url": "https://example.com/webhook" // optional, string
}

Response 201 Created

{
  "batchId": "batch_abc123xyz",
  "status": "pending",
  "requestCount": 2,
  "createdAt": "2025-01-15T10:30:00Z"
}

Error Responses

// 400 Bad Request - Invalid request
// 401 Unauthorized - Invalid API keys
GET /v1/batch

Get all batch jobs for the authenticated tenant/project.

Query Parameters

status optional string Filter by status: "pending", "processing", "completed", "failed"
limit optional integer Number of items to return (default: 20)

Response 200 OK

{
  "batches": [
    {
      "batchId": "batch_abc123",
      "status": "completed",
      "requestCount": 2,
      "createdAt": "2025-01-15T10:30:00Z",
      "completedAt": "2025-01-15T14:20:00Z"
    }
  ]
}

Error Responses

// 401 Unauthorized - Invalid API keys
GET /v1/batch/:batchJobId

Get details of a specific batch job.

Response 200 OK

{
  "batchId": "batch_abc123xyz",
  "status": "completed",
  "requestCount": 2,
  "completedCount": 2,
  "failedCount": 0,
  "createdAt": "2025-01-15T10:30:00Z",
  "completedAt": "2025-01-15T14:20:00Z"
}

Error Responses

// 404 Not Found - Batch job not found
GET /v1/batch/:batchJobId/results

Get the results of a completed batch job.

Response 200 OK

{
  "batchId": "batch_abc123xyz",
  "status": "completed",
  "results": [
    {
      "custom_id": "request-1",
      "status": "completed",
      "completion": "Hola",
      "model": "gpt-4",
      "usage": {
        "prompt_tokens": 8,
        "completion_tokens": 2,
        "total_tokens": 10
      }
    },
    {
      "custom_id": "request-2",
      "status": "completed",
      "completion": "2+2 equals 4",
      "model": "gpt-4",
      "usage": {
        "prompt_tokens": 6,
        "completion_tokens": 5,
        "total_tokens": 11
      }
    }
  ]
}

Error Responses

// 404 Not Found - Batch job not found
// 425 Too Early - Batch job not yet completed
POST /v1/batch/:batchJobId/cancel

Cancel a pending or processing batch job.

Response 200 OK

{
  "batchId": "batch_abc123xyz",
  "status": "cancelled",
  "message": "Batch job cancelled successfully"
}

Error Responses

// 404 Not Found - Batch job not found
// 409 Conflict - Batch job cannot be cancelled
POST /v1/providers

Configure OpenAI or Anthropic provider credentials for your project.

Request Body

{
  "providerType": "openai",            // required: "openai" or "anthropic"
  "apiKey": "sk-...",                  // required, string
  "organizationId": "org-..."          // optional (OpenAI only)
}

Response 200 OK

{
  "provider": {
    "id": "prov_abc123",
    "providerType": "openai",
    "configured": true,
    "createdAt": "2025-01-15T10:30:00Z"
  }
}
POST /v1/providers/test

Test connection to LLM provider with configured credentials.

Request Body

{
  "providerType": "openai"             // required: "openai" or "anthropic"
}

Response 200 OK

{
  "success": true,
  "message": "Connection successful",
  "providerType": "openai"
}

Mailer Service

Transactional email sending, template management with Handlebars support, multi-provider support (Mailgun, SendGrid), and email logs.

POST /v1/emails/send

Send a transactional email using configured provider.

Request Body

{
  "to": "user@example.com",            // required, string (email format)
  "subject": "Welcome!",               // required, string
  "html": "<h1>Welcome!</h1>",              // optional, string (HTML body)
  "text": "Welcome!",                  // optional, string (plain text body)
  "templateId": "tmpl_xyz789",         // optional, string (use template instead)
  "templateData": {                    // optional, object (variables for template)
    "name": "John Doe",
    "verificationUrl": "https://..."
  },
  "from": "noreply@example.com"        // optional, string (override default sender)
}

Response 200 OK

{
  "messageId": "msg_abc123xyz",
  "status": "sent",
  "to": "user@example.com",
  "sentAt": "2025-01-15T10:35:00Z"
}

Error Responses

// 400 Bad Request - Invalid request
// 401 Unauthorized
GET /v1/logs

Retrieve all email logs for the tenant/project.

Query Parameters

limit optional integer Number of items to return (default: 50)
offset optional integer Pagination offset (default: 0)

Response 200 OK

{
  "logs": [
    {
      "id": "log_abc123",
      "to": "user@example.com",
      "subject": "Welcome!",
      "status": "delivered",
      "sentAt": "2025-01-15T10:35:00Z"
    }
  ],
  "total": 125,
  "limit": 50,
  "offset": 0
}

Error Responses

// 401 Unauthorized
GET /v1/stats

Get email sending statistics for the tenant/project.

Response 200 OK

{
  "total": 1250,
  "sent": 1200,
  "delivered": 1180,
  "bounced": 10,
  "failed": 60
}

Error Responses

// 401 Unauthorized
POST /v1/templates

Create a new email template with Handlebars support.

Request Body

{
  "name": "Welcome Email",             // required, string
  "templateKey": "welcome-email",      // optional, string (unique identifier)
  "subject": "Welcome {{name}}!",      // required, string (Handlebars)
  "html": "<h1>Welcome {{name}}!</h1>", // required, string (Handlebars)
  "text": "Welcome {{name}}!"          // optional, string (Handlebars)
}

Response 201 Created

{
  "id": "tmpl_xyz789",
  "name": "Welcome Email",
  "templateKey": "welcome-email",
  "subject": "Welcome {{name}}!",
  "createdAt": "2025-01-15T10:30:00Z"
}

Error Responses

// 400 Bad Request - Invalid request
// 401 Unauthorized
GET /v1/templates

Get all email templates for the tenant/project.

Response 200 OK

{
  "templates": [
    {
      "id": "tmpl_xyz789",
      "name": "Welcome Email",
      "templateKey": "welcome-email",
      "subject": "Welcome {{name}}!",
      "createdAt": "2025-01-15T10:30:00Z"
    }
  ]
}

Error Responses

// 401 Unauthorized
GET /v1/templates/:id

Get template by ID.

Response 200 OK

{
  "id": "tmpl_xyz789",
  "name": "Welcome Email",
  "templateKey": "welcome-email",
  "subject": "Welcome {{name}}!",
  "html": "<h1>Welcome {{name}}!</h1>",
  "text": "Welcome {{name}}!",
  "createdAt": "2025-01-15T10:30:00Z",
  "updatedAt": "2025-01-15T10:30:00Z"
}

Error Responses

// 404 Not Found - Template not found
POST /v1/providers

Configure a new email provider (Mailgun or SendGrid).

Request Body

{
  "name": "Primary Mailgun",           // required, string
  "type": "mailgun",                   // required: "mailgun" or "sendgrid"
  "config": {                          // required, object (provider-specific)
    "apiKey": "key-...",
    "domain": "mg.example.com",        // Mailgun only
    "fromEmail": "noreply@example.com"
  },
  "isDefault": true                    // optional, boolean
}

Response 201 Created

{
  "id": "prov_abc123",
  "name": "Primary Mailgun",
  "type": "mailgun",
  "isDefault": true,
  "createdAt": "2025-01-15T10:30:00Z"
}

Error Responses

// 400 Bad Request - Invalid request
GET /v1/providers

List all email providers.

Response 200 OK

{
  "providers": [
    {
      "id": "prov_abc123",
      "name": "Primary Mailgun",
      "type": "mailgun",
      "isDefault": true,
      "createdAt": "2025-01-15T10:30:00Z"
    }
  ]
}

Notification Service

In-app notification management with read/unread tracking, broadcast notifications, and TTL/expiration support (default 30 days).

POST /notifications

Create a new in-app notification. Set userId to null for broadcast notifications.

Request Body

{
  "userId": "550e8400-e29b-41d4-a716-446655440000", // optional (null for broadcast)
  "title": "Welcome!",                 // required, string
  "message": "Thanks for joining...",  // required, string
  "type": "info",                      // optional: "info", "success", "warning", "error", "custom"
  "data": {                            // optional, object (custom data payload)
    "actionUrl": "/dashboard",
    "priority": "high"
  },
  "expiresAt": "2025-02-15T10:30:00Z" // optional, date-time (default 30 days)
}

Response 201 Created

{
  "id": "notif_abc123xyz",
  "userId": "550e8400-e29b-41d4-a716-446655440000",
  "title": "Welcome!",
  "message": "Thanks for joining...",
  "type": "info",
  "data": { ... },
  "read": false,
  "createdAt": "2025-01-15T10:30:00Z",
  "expiresAt": "2025-02-15T10:30:00Z"
}

Error Responses

// 400 Bad Request - Invalid request
// 401 Unauthorized
GET /notifications

Get notifications with optional filtering by user, read status, or type.

Query Parameters

userId optional string Filter by user ID
read optional boolean Filter by read status
type optional string Filter by notification type
limit optional integer Number of items to return (default: 20)
offset optional integer Pagination offset (default: 0)

Response 200 OK

{
  "notifications": [
    {
      "id": "notif_abc123",
      "userId": "550e8400-e29b-41d4-a716-446655440000",
      "title": "Welcome!",
      "message": "Thanks for joining...",
      "type": "info",
      "read": false,
      "createdAt": "2025-01-15T10:30:00Z"
    }
  ],
  "total": 42,
  "limit": 20,
  "offset": 0
}

Error Responses

// 401 Unauthorized
GET /notifications/:id

Get notification by ID.

Response 200 OK

{
  "id": "notif_abc123xyz",
  "userId": "550e8400-e29b-41d4-a716-446655440000",
  "title": "Welcome!",
  "message": "Thanks for joining...",
  "type": "info",
  "data": { ... },
  "read": false,
  "createdAt": "2025-01-15T10:30:00Z",
  "expiresAt": "2025-02-15T10:30:00Z"
}

Error Responses

// 404 Not Found - Notification not found
DELETE /notifications/:id

Soft delete a notification.

Response 204 No Content

No response body. Notification deleted successfully.

Error Responses

// 404 Not Found - Notification not found
PATCH /notifications/:id/read

Mark notification as read.

Response 200 OK

{
  "id": "notif_abc123",
  "userId": "550e8400-e29b-41d4-a716-446655440000",
  "title": "Welcome!",
  "message": "Thanks for joining...",
  "read": true,
  "readAt": "2025-01-15T11:00:00Z",
  "createdAt": "2025-01-15T10:30:00Z"
}

Error Responses

// 404 Not Found - Notification not found
PATCH /notifications/mark-all-read

Mark all notifications as read for a specific user.

Query Parameters

userId required string User ID to mark notifications for

Response 200 OK

{
  "message": "All notifications marked as read",
  "count": 12
}

Error Responses

// 400 Bad Request - userId required

Common Error Codes

Status Code Error Description
400 Bad Request Invalid request parameters or body
401 Unauthorized Missing or invalid authentication credentials
403 Forbidden Valid credentials but insufficient permissions
404 Not Found Resource does not exist
409 Conflict Resource already exists (e.g., duplicate email)
410 Gone Resource expired or permanently deleted
423 Locked Resource is locked (e.g., account locked)
425 Too Early Request too early (e.g., batch not ready)
429 Too Many Requests Rate limit exceeded
500 Internal Server Error Server error, please retry
503 Service Unavailable Service temporarily unavailable

Next Steps