Organizations

Organizations let multiple users share lists, posting permissions, and (when connected) a shared LinkedIn credential for company-page posting. Roles are owner, admin, and member.

Create vs. join (mind which endpoint you call).

  • Create an organization → POST /api/organizations (Session or Bearer; Subscriber tier).
  • Join a public organization → POST /api/user/organizations (Session or Bearer; body { "organizationId": "..." }). Returns 201 { "message": "Joined organization successfully", "membership": { ... } }; joining a private org returns 403.
  • List the caller's organizations → GET /api/user/organizations (Session or Bearer).

Endpoint table

MethodPathAuthDescription
GET/api/organizationsSession or BearerList organizations. Query: ?public=true for all public orgs, ?userId=... to filter by member.
POST/api/organizationsSession or BearerCreate an organization. Body: name, description, isPublic.
GET/api/organizations/:idSession or BearerGet an organization.
PUT/api/organizations/:idSession or BearerUpdate an organization.
DELETE/api/organizations/:idSession or BearerDelete an organization.
GET/api/organizations/:id/membersSession or BearerList members and their roles.
POST/api/organizations/:id/membersSession or BearerAdd a member. Body: { "userId": "...", "role": "member" }.
PUT/api/organizations/:id/members/:userIdSession or BearerUpdate a member's role (and optionally active).
DELETE/api/organizations/:id/members/:userIdSession or BearerRemove a member.
GET/api/organizations/:id/usersSession or BearerUsers in the organization with role details.
GET/api/organizations/:id/linkedin/statusSession or BearerLinkedIn credential status for the org.
DELETE/api/organizations/:id/linkedin/credentialSession or BearerDisconnect the shared LinkedIn credential.
GET/api/organizations/:id/linkedin/sync-pagesSession or BearerList the discovered LinkedIn company pages.
POST/api/organizations/:id/linkedin/sync-pagesSession or BearerRe-discover and sync LinkedIn company pages.
GET/api/organizations/:id/linkedin/assignmentsSession or BearerPage assignments per member.
PUT/api/organizations/:id/linkedin/assignmentsSession or BearerUpdate page assignments.

Creating an organization

POST /api/organizations
Content-Type: application/json

{ "name": "Acme Dev Team", "description": "Internal engineering org.", "isPublic": false }

Response (201): the created org is returned under organization:

{
  "message": "Organization created successfully",
  "organization": {
    "id": "org_001",
    "name": "Acme Dev Team",
    "description": "Internal engineering org.",
    "isPublic": false,
    "createdAt": "2025-06-11T10:00:00.000Z"
  }
}

Members

POST /api/organizations/org_001/members
Content-Type: application/json

{ "userId": "clx9user00003", "role": "member" }

Roles: owner, admin, member. You must be an owner or admin to add or change roles. The last owner cannot be demoted or removed; the server returns 400.

PUT /api/organizations/org_001/members/clx9user00003
Content-Type: application/json

{ "role": "admin" }

Response (200):

{
  "message": "Member role updated successfully",
  "membership": {
    "id": "mem_xyz001",
    "userId": "clx9user00003",
    "organizationId": "org_001",
    "role": "admin",
    "active": true,
    "createdAt": "2025-06-11T10:00:00.000Z"
  }
}

Pass "active": false alongside role to suspend a member's access without removing them from the organization.

LinkedIn organization integration

When an organization's owners or admins connect a shared LinkedIn credential, member-authored messages can be cross-posted as company posts.

Start the OAuth flow:

GET /api/auth/linkedin/org-authorize?organizationId=org_001

This redirects the browser to LinkedIn requesting the rw_organization_admin scope. On completion, the discovered LinkedIn company pages are stored as OrgLinkedInPage records bound to the organization.

MethodPathPurpose
GET /api/organizations/:id/linkedin/statusReturns { "connected": true, "expiresAt": "..." } plus the discovered pages.
POST /api/organizations/:id/linkedin/sync-pagesRe-discover and upsert company pages.
GET /api/organizations/:id/linkedin/assignmentsReturns which member is assigned to post to which page.
PUT /api/organizations/:id/linkedin/assignmentsReplace the assignment map atomically.
DELETE /api/organizations/:id/linkedin/credentialRevoke the shared credential (assignments are cleared server-side).

When a member with an active assignment cross-posts with crossPostToLinkedIn: true (and no explicit linkedInTargets), the post is published using the org credential as the assigned company page. Without an assignment (or after disconnect) cross-posts fall back to the member's personal LinkedIn identity.

For personal LinkedIn pages (not org-bound), see LinkedIn Integration.