REST API Reference

API Documentation

Complete REST API reference for the BackSuit platform. Base URL: https://api.backsuit.com/

Authentication Methods

JWT Bearer Token
http
Authorization: Bearer <access_token>

Access tokens expire in 1 hour. Refresh tokens expire in 30 days.

API Key
http
X-API-Key: pa_your_api_key_here

Use for server-to-server integrations. Keys are shown only once on creation.

Tenant Context
http
X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000

Optional. Scopes requests to a specific tenant workspace.

Authentication Endpoints

POST/api/v1/auth/registerRegister a new user

Request

json
{
  "email": "user@example.com",
  "password": "securePassword123",
  "username": "johndoe",
  "full_name": "John Doe"
}

Response

json
// 201 Created
{
  "message": "User registered successfully",
  "user": { "id": 1, "email": "user@example.com", ... },
  "access_token": "eyJhbGci...",
  "refresh_token": "eyJhbGci...",
  "token_type": "Bearer"
}
Notes: Without X-Tenant-ID creates a platform admin user. With X-Tenant-ID creates a tenant-scoped user. Password must be at least 8 characters.
POST/api/v1/auth/loginAuthenticate and get tokens

Request

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

Response

json
// 200 OK
{
  "message": "Login successful",
  "user": { "id": 1, "email": "user@example.com", ... },
  "access_token": "eyJhbGci...",
  "refresh_token": "eyJhbGci...",
  "token_type": "Bearer"
}
POST/api/v1/auth/refreshRefresh access token

Request

json
{
  "refresh_token": "eyJhbGci..."
}

Response

json
// 200 OK
{
  "access_token": "eyJhbGci...",
  "token_type": "Bearer"
}
GET/api/v1/auth/meGet current authenticated user

Response

json
// 200 OK
{
  "user": {
    "id": 1,
    "email": "user@example.com",
    "username": "johndoe",
    "full_name": "John Doe",
    "role": "Admin",
    "is_platform_admin": false,
    "tenant_id": "550e8400-...",
    "created_at": "2025-01-01T00:00:00.000000"
  }
}

OAuth Endpoints

Supported Providers: googlegithublinkedinfacebook
GET/api/v1/auth/oauth/{provider}Initiate OAuth flow — redirects to provider
GET/api/v1/auth/oauth/{provider}/callbackOAuth callback — handled automatically
Notes: On success redirects to: {FRONTEND_URL}/oauth/callback?access_token=...&refresh_token=... — Creates new user if email doesn't exist; links to existing account if it does.

API Key Management

GET/api/v1/auth/api-keysList all API keys

Response

json
// 200 OK
{
  "api_keys": [
    {
      "id": 1,
      "name": "My Production Key",
      "prefix": "pa_123456",
      "is_active": true,
      "request_count": 42,
      "last_used_at": "2025-01-01T12:00:00.000000"
    }
  ]
}
POST/api/v1/auth/api-keysCreate a new API key

Request

json
{ "name": "My Production Key" }

Response

json
// 201 Created
{
  "message": "API key created successfully",
  "api_key": "pa_1234567890abcdef...",
  "prefix": "pa_123456",
  "warning": "Save this key securely. You will not be able to see it again."
}
Notes: The full API key is only shown once on creation. Store it securely.
DELETE/api/v1/auth/api-keys/{key_id}Delete an API key

Response

json
// 200 OK
{ "message": "API key deleted successfully" }

Profile Management

PATCH/api/v1/auth/profileUpdate user profile (all fields optional)

Request

json
{
  "full_name": "John Doe",
  "username": "johndoe",
  "profile_image": "https://example.com/profile.jpg"
}

Response

json
// 200 OK
{
  "message": "Profile updated successfully",
  "user": { "id": 1, "email": "...", "username": "johndoe", ... }
}
POST/api/v1/auth/change-passwordChange user password

Request

json
{
  "current_password": "oldPassword123",
  "new_password": "newPassword456"
}

Response

json
// 200 OK
{ "message": "Password changed successfully" }

Message / Contact Endpoints

POST/api/v1/contactSubmit a contact message

Request

json
{
  "name": "John Doe",
  "email": "user@example.com",
  "subject": "Question about API",
  "message": "How do I get an API key?"
}

Response

json
// 201 Created
{ "message": "Message sent successfully" }
GET/api/v1/messagesList messages (authenticated)

Response

json
// 200 OK
{
  "messages": [
    {
      "id": 1,
      "subject": "Welcome",
      "body": "...",
      "sender": { "id": 2, "full_name": "Admin" },
      "read": false,
      "created_at": "2025-01-01T00:00:00.000000"
    }
  ]
}

Article Endpoints

GET/api/v1/tenants/{tenant_id}/articlesList articles for a tenant

Response

json
// 200 OK
{
  "articles": [
    {
      "id": 1,
      "title": "My Article",
      "slug": "my-article",
      "status": "published",
      "category_id": 2,
      "created_at": "2025-01-01T00:00:00.000000"
    }
  ],
  "total": 1, "page": 1, "per_page": 20
}
POST/api/v1/tenants/{tenant_id}/articlesCreate a new article

Request

json
{
  "title": "My Article",
  "content": "Article body in markdown...",
  "category_id": 1,
  "status": "draft"
}

Response

json
// 201 Created
{ "article": { "id": 1, "title": "My Article", ... } }
GET/api/v1/tenants/{tenant_id}/articles/{article_id}Get a single article
PATCH/api/v1/tenants/{tenant_id}/articles/{article_id}Update an article

Request

json
{ "title": "Updated Title", "status": "published" }
DELETE/api/v1/tenants/{tenant_id}/articles/{article_id}Delete an article
POST/api/v1/tenants/{tenant_id}/articles/generateGenerate article with AI

Request

json
{
  "prompt": "Write about the future of AI in content creation",
  "category_id": 1,
  "tone": "professional",
  "length": "medium"
}

Response

json
// 201 Created
{
  "article": {
    "id": 5,
    "title": "The Future of AI in Content Creation",
    "content": "...",
    "status": "draft"
  }
}
GET/api/v1/tenants/{tenant_id}/articles/searchSearch articles

Request

json
// Query params: ?q=keyword&status=published&category_id=1

Category Endpoints

GET/api/v1/tenants/{tenant_id}/categoriesList all categories

Response

json
// 200 OK
{ "categories": [{ "id": 1, "name": "Tech", "slug": "tech", "description": "...", "article_count": 5 }] }
POST/api/v1/tenants/{tenant_id}/categoriesCreate a category

Request

json
{ "name": "Technology", "slug": "technology", "description": "Tech articles" }
PATCH/api/v1/tenants/{tenant_id}/categories/{category_id}Update a category
DELETE/api/v1/tenants/{tenant_id}/categories/{category_id}Delete a category

Comment Endpoints

GET/api/v1/tenants/{tenant_id}/articles/{article_id}/commentsList comments on an article
POST/api/v1/tenants/{tenant_id}/articles/{article_id}/commentsPost a comment

Request

json
{ "content": "Great article!" }
DELETE/api/v1/tenants/{tenant_id}/comments/{comment_id}Delete a comment

Team Management

GET/api/v1/tenants/{tenant_id}/teamList team members

Response

json
// 200 OK
{ "members": [{ "id": 1, "full_name": "Jane", "role": "Editor", "email": "..." }] }
PATCH/api/v1/tenants/{tenant_id}/team/{user_id}Update member role

Request

json
{ "role": "Editor" }
DELETE/api/v1/tenants/{tenant_id}/team/{user_id}Remove a team member

Tenant Management

GET/api/v1/tenantsList tenants for current user
POST/api/v1/tenantsCreate a new tenant

Request

json
{
  "name": "My Blog",
  "slug": "my-blog",
  "domain": "myblog.com",
  "description": "A personal tech blog"
}
GET/api/v1/tenants/{tenant_id}Get tenant details
PATCH/api/v1/tenants/{tenant_id}Update tenant
DELETE/api/v1/tenants/{tenant_id}Delete tenant

Invitation Endpoints

POST/api/v1/tenants/{tenant_id}/invitationsInvite a user to a tenant

Request

json
{ "email": "newuser@example.com", "role": "Editor" }

Response

json
// 201 Created
{ "message": "Invitation sent", "invitation_token": "abc123..." }
POST/api/v1/invitations/acceptAccept an invitation

Request

json
{ "token": "abc123..." }
GET/api/v1/tenants/{tenant_id}/invitationsList pending invitations

Article Scheduling

POST/api/v1/tenants/{tenant_id}/articles/{article_id}/scheduleSchedule article for publishing

Request

json
{
  "scheduled_at": "2025-06-01T09:00:00Z",
  "timezone": "America/New_York"
}

Response

json
// 200 OK
{ "message": "Article scheduled", "scheduled_at": "2025-06-01T09:00:00Z" }
DELETE/api/v1/tenants/{tenant_id}/articles/{article_id}/scheduleCancel scheduled publishing
GET/api/v1/tenants/{tenant_id}/scheduledList all scheduled articles

Social Media Posting

GET/api/v1/tenants/{tenant_id}/social-accountsList connected social media accounts
POST/api/v1/tenants/{tenant_id}/articles/{article_id}/publish-socialPost article to social media

Request

json
{
  "platforms": ["twitter", "linkedin"],
  "custom_message": "Check out our latest article!",
  "schedule_at": null
}

Subscription Endpoints

GET/api/v1/subscriptions/plansList available subscription plans

Response

json
// 200 OK
{ "plans": [{ "id": "pro", "name": "Pro", "price": 29, "features": [...] }] }
GET/api/v1/subscriptions/currentGet current subscription
POST/api/v1/subscriptionsCreate / upgrade subscription

Request

json
{ "plan_id": "pro", "payment_method_id": "pm_xxx" }
DELETE/api/v1/subscriptions/cancelCancel subscription

System Administration (Global Admin)

All admin endpoints require is_platform_admin: true on the user account.
GET/api/v1/admin/dashboardPlatform overview — user counts, revenue, active tenants
GET/api/v1/admin/insightsPlatform insights and growth metrics
GET/api/v1/admin/analytics/contentContent analytics across all tenants
GET/api/v1/admin/analytics/revenueRevenue analytics and subscription breakdown
GET/api/v1/admin/tenantsList all tenants
PATCH/api/v1/admin/tenants/{tenant_id}Update tenant settings
GET/api/v1/admin/usersList all users
PATCH/api/v1/admin/users/{user_id}/roleUpdate user platform role

Request

json
{ "is_platform_admin": true }
GET/api/v1/admin/audit-logsGet audit logs

Response

json
// 200 OK
{ "logs": [{ "id": 1, "action": "user.login", "user_id": 1, "ip": "127.0.0.1", "created_at": "..." }] }

Health Check

GET/healthServer health check

Response

json
// 200 OK
{ "status": "healthy", "version": "1.0.0", "db": "connected" }

Error Responses

400
Bad Request
Invalid request body or parameters
401
Unauthorized
Missing or invalid authentication token
403
Forbidden
Insufficient permissions for this action
404
Not Found
Resource does not exist
409
Conflict
Resource already exists (e.g. duplicate email)
422
Unprocessable
Validation failed for request data
429
Rate Limited
Too many requests — slow down
500
Server Error
Internal server error

Standard Error Response Format

json
{
  "error": "Unauthorized",
  "message": "Invalid or expired token",
  "status": 401
}