logicspike/docs

Authentication & Team

API Specification: Team Management

Last Updated: 2026-02-28

Service Owner

apps/manager (The Platform Core Service) Why? Team Management is inseparable from Authentication and Tenant Metadata. Splitting it would cause distributed complexity.

Base URL

/manager/team (Proxied through the Gateway, scoped to the current tenant via JWT x-tenant-id)

1. Invitations (Hiring)

POST /invitations

Send an invite to a new member.

  • Auth: Required (team:members.invite)
  • Body:
    {
      "email": "chloe@dev.com",
      "role_id": "role_developer_123"
    }
  • Response (201 Created):
    {
      "data": {
        "id": "inv_abc123",
        "token": "secret_token_xyz", // Only returned once!
        "expires_at": "2026-02-19T10:00:00Z",
        "status": "pending"
      }
    }

GET /invitations/:token (Public)

Validate an invite token (for the landing page).

  • Auth: Public
  • Response (200 OK):
    {
      "data": {
        "tenant_name": "TechStartup",
        "inviter_name": "Ben",
        "email": "chloe@dev.com", // The intended recipient
        "is_valid": true
      }
    }

POST /invitations/:token/accept

Accept the invite and join the tenant.

  • Auth: Required (User must be logged in)
  • Response (200 OK):
    {
      "data": {
        "membership_id": "mem_new_123"
      }
    }

2. Memberships (Staff Management)

GET /members

List all staff in the current tenant.

  • Auth: Required (team:members.read)
  • Response (200 OK):
    {
      "data": [
        {
          "id": "mem_1",
          "user": { "id": "u1", "name": "Ayva", "email": "ayva@example.com", "avatar": "..." },
          "role": { "id": "role_owner", "name": "Owner" },
          "joined_at": "2026-01-01..."
        }
      ],
      "meta": { "total": 5, "page": 1 }
    }

PATCH /members/:id

Update a member's role (Promotion).

  • Auth: Required (team:members.manage)
  • Body:
    {
      "role_id": "role_admin_456"
    }
  • Response (200 OK): Returns updated membership.

DELETE /members/:id

Remove a staff member (Offboarding).

  • Auth: Required (team:members.remove)
  • Body (Optional - For Resource Transfer):
    {
      "transfer_assets_to": "mem_owner_1" // Logic: Transfer posts/files to Owner
    }
  • Response (200 OK):
    {
      "data": { "success": true, "revoked_sessions": 3 }
    }

3. Roles (RBAC)

GET /roles

List available roles (System + Custom).

  • Auth: Required (team:roles.read)
  • Response:
    {
      "data": [
        { "id": "role_owner", "name": "Owner", "is_system": true, "permissions": ["*"] },
        { "id": "role_dev", "name": "Developer", "is_system": false, "permissions": ["blog:posts.read", "blog:posts.update"] }
      ]
    }

4. Error Codes

Code HTTP Meaning
INVITE_EXPIRED 400 The token is past its expiration date.
INVITE_EMAIL_MISMATCH 403 The logged-in user email != invite email.
MEMBER_NOT_FOUND 404 Member ID does not exist in this tenant.
CANNOT_REMOVE_SELF 400 You cannot delete your own membership.
CANNOT_DOWNGRADE_OWNER 403 The Owner role cannot be changed.
Authentication & Team