Community context

Almost everything in Babele is scoped to a community, so most endpoints take a communityId — as a route segment, a query parameter, or a field in the request body. This guide covers where to find your community ID, where the parameter goes, when it is required and when it is optional, and what the API does when you leave it out.

Finding your community ID

Most endpoints require the community ID as an URL parameter, query parameter or in the request body. To find your community ID, login to the Babele platform and check the URL of the page in the browser URL location box. The community ID is the numeric part of the URL that immediately follows /community. In https://app.babele.co/community/1234, the community ID would be 1234. A page whose URL has no /community/{id} segment carries no community context at all.

The API can also tell you:

  • GET /api/User/GetMyCommunities returns every community the authenticated account belongs to, each with its id and name. This is the usual way for an integration to discover the IDs it is allowed to use.
  • GET /api/Project/GetOverview?id={id} returns a communities array naming every community a project is publicly visible in, each with its id and name. Use it when you know the project but not the community.

What changed: one project, many communities

Babele used to model the project–community relationship as 1:1. A project lived in exactly one community, so a projectId was enough to identify everything about it, and most endpoints never had to ask which community you meant.

That relationship is now N:M, expressed through a link called CommunityProject — one per (community, project) pair. Two consequences drive everything else on this page:

  • A project can belong to several communities at once. The same project can be enrolled in one program in community 999 and in a different program in community 1000, with its own canvas, its own mentors, its own KPI values and its own discussions in each. Asking for "the project" without saying which community is now ambiguous, which is why so many endpoints ask you to name one.
  • A project can also exist standalone, with no community at all — visitable with no community context. A project can be standalone and belong to communities at the same time. This is why some reads accept no communityId rather than demanding one.

What is per-community and what is per-project

Per-community, stored against the CommunityProject link: the business-model canvas — its sections, paragraphs and paragraph comments — program enrolments, the community's project form and the project's answers to it, community-project KPI definitions and KPI values, discussions raised in that community, and the link's own privacy level. None of it is visible from another community.

Per-project, shared across every community the project belongs to: the project's own descriptive fields — name, description, media, location, social links — its sustainable development goals, and its Core Team. The Core Team is a single global list, visible from any community context the project belongs to. Follower, mentor and custom circles may be scoped either to the project or to one community-project link.

Authorization follows the same split. A community administrator's powers stop at their own community's boundary, even for a project that also belongs to a community they do not administer. Programs are strictly per-community: a program attached to one community is never visible from another.

Joining and leaving a community

Two endpoints manage the links directly. They replace the old 1:1 "move into community" behaviour.

POST /api/Project/AddToCommunity

curl -X POST "https://api.babele.co/api/Project/AddToCommunity?projectId=1714&targetCommunityId=1000"

Note the parameter is called targetCommunityId, not communityId. Adding a project that already has an active link returns 409 Conflict (ProjectAlreadyInCommunityException); adding one whose link exists but has been disabled re-enables that link instead of creating a second one. The caller must be an administrator of the target community who also administers one of the communities the project already belongs to — a project that belongs to no community yet can be added by any administrator of the target community.

POST /api/Project/RemoveFromCommunity

curl -X POST "https://api.babele.co/api/Project/RemoveFromCommunity?projectId=1714&communityId=1000"

This one marks the link disabled. It does not delete the project, which goes on existing standalone and in whatever other communities it belongs to. The caller must administer the community being removed from.

Where communityId goes

There are four patterns. Which one an endpoint uses is fixed — check the endpoint's own reference page before you guess. The examples below are trimmed to show placement only; every one of these endpoints also needs the Authorization: Bearer <token> header described under Authentication and Authorization.

A route segment

The community ID is part of the path. It cannot be omitted: leave it out and the route simply does not match, so you get a 404 rather than an API error.

DELETE /api/Methodology/{communityId}/{id}

curl -X DELETE "https://api.babele.co/api/Methodology/999/73"

Other examples: POST /api/Project/{communityId}/bulk/Tag, GET /api/Community/{id}/ApplicationDefinitions.

A query parameter

The most common pattern on GET endpoints. It sits alongside the resource ID.

GET /api/Project/GetOverview

curl -X GET "https://api.babele.co/api/Project/GetOverview?id=1714&communityId=999"

Other examples: GET /api/Project/GetByMethodology, GET /api/KpiReport/GetKpiChartReportsForOverview, GET /api/SurveyForm/GetAll.

A request-DTO field

On writes, the community ID travels in the JSON body next to the rest of the resource. On several endpoints it is not only read but stored, so changing it on an update moves the resource to another community.

POST /api/Survey/survey-definition

curl -X POST "https://api.babele.co/api/Survey/survey-definition" \
 -H "Content-Type: application/json" \
 -d '{"communityId":999,"formId":1258,"name":"Quarterly impact survey"}'

Other examples: POST /api/ApplicationDefinition, PUT /api/ApplicationDefinition/{id}, PUT /api/Survey/survey-definitions/{surveyId}.

A filter field inside a POST body

List and search endpoints are POST because their filter is a JSON object. communityId is one field of that filter, and it is what scopes the whole query — it is never a wildcard.

POST /api/Project/GetByCommunity

curl -X POST "https://api.babele.co/api/Project/GetByCommunity" \
 -H "Content-Type: application/json" \
 -d '{"communityId":999,"skip":0,"take":50,"orderBy":0}'

Other examples: POST /api/Community/GetUserList, POST /api/Project/GetUserList, POST /api/Project/GetResourceList.

Required or optional, and why

The N:M change pushed communityId in two directions at once, and the rule of thumb follows from what each endpoint is for:

If the endpoint reads a project and could sensibly answer without a community, communityId is optional. Everything else — every write, and every read whose answer only exists inside a community — requires it.

Reads that loosened to optional, so that standalone projects stay reachable. These accept a missing communityId and behave differently, not badly, when you leave the parameter out:

  • GET /api/Project/GetOverview
  • GET /api/Project/GetOverviewSummary
  • GET /api/Project/GetEditInfoOverview
  • GET /api/KpiDefinition/GetByProject
  • GET /api/KpiValue/GetPending
  • POST /api/Project/GetResourceList — the communityId inside the filter body is nullable

POST /api/Project/Create belongs here too: its body communityId is nullable, and omitting it creates a standalone project rather than failing.

Writes and community-scoped reads that tightened to required. Scope has to be explicit, because the server can no longer infer which community you meant from the project alone:

  • GET /api/Project/Disable, Follow, Unfollow, ApplyToTeam, IsProjectTeamMember, and DELETE /api/Project/Delete
  • POST /api/Project/AddToCommunity — as targetCommunityId — and POST /api/Project/RemoveFromCommunity
  • GET /api/Project/GetByMethodology
  • GET /api/KpiDefinition/GetByMethodology
  • GET /api/KpiReport/GetByProject, GetKpiChartReportsForOverview
  • GET /api/ProjectTracking/Details, SearchOverview
  • GET /api/Survey/project-survey-definitions, project-survey-responses, user-survey-responses
  • POST /api/Community/GetUserList, POST /api/Project/GetUserList — in the filter body

Team membership is the case that surprises people. The Core Team is project-scoped now, yet every team endpoint still requires communityId: it is the authorization and audit context, and it selects the community-project link that memberships and permissions are read through. It is required even though the team list it returns is global.

What happens when you omit it

Omitting an optional communityId

You get the standalone view of the project: the project as it exists in its own right, with every community-scoped field emptied. On GET /api/Project/GetOverview that means the caller must hold a membership of the project itself, and:

  • pendingParagraphs and openDiscussions come back []
  • form, answers and kpiDefinitions come back null
  • discussionCount, resourceCount and networkCount are 0
  • isCommunityAdmin and canEditCircles are false
  • userInvitationPolicy is 4 (None)
  • communityIds is [] and mainCommunityId is null
  • communities is still populated, listing every community the project is publicly visible in

Supply communityId on the same call and you get the project as it exists inside that one community, with its discussions, its pending paragraphs, that community's project form and answers, the applicable KPI definitions and the community-scoped permission flags. See "Get a project overview" on the Projects page for the full field-by-field breakdown.

Omitting a required communityId

A missing communityId is never treated as "all communities". The API treats the absent value as 0, and 0 is not a valid community, so the request goes wrong in one of three ways depending on the endpoint:

  • 500 with an error discriminator. The body names the exception in an error field — CommunityNotFoundException or CannotAccessToCommunityException. POST /api/Project/GetByCommunity and POST /api/Community/GetUserList fail this way.
  • 403 Forbidden. Endpoints that check a community permission before querying reject community 0 as a permission failure. GET /api/ProjectTracking/SearchOverview and GET /api/KpiReport/GetKpiChartReportsForOverview behave this way.
  • 200 with silently wrong data. This is the dangerous one. Endpoints that resolve the (project, community) pair find nothing for community 0 and return an empty or partial result with no error at all. GET /api/Project/GetByMethodology returns []. POST /api/Project/GetUserList returns a body, but with a partial team, a count that is too low, isMember and isAdmin false and empty pending arrays.

The first case is the only one that gives you a usable signal. It looks like this:

Response

{
    "error": "CommunityNotFoundException",
    "errorCode": null,
    "message": "An error has occurred."
}

communityId at a glance

EndpointWhere it goesRequired?If you omit it
POST /api/Project/GetByCommunityFilter bodyRequired500 CommunityNotFoundException
GET /api/Project/GetOverviewQueryOptionalThe standalone project view
GET /api/ProjectTracking/SearchOverviewQueryRequired403 Forbidden
GET /api/KpiReport/GetKpiChartReportsForOverviewQueryRequired403 Forbidden
POST /api/Community/GetUserListFilter bodyRequired500 CommunityNotFoundException
POST /api/Project/GetUserListFilter bodyRequired200 with a partial team and false permission flags
GET /api/SurveyForm/GetAllQueryRequired200 with an empty list
POST /api/Survey/survey-definitionRequest bodyRequiredThe survey is filed under community 0
PUT /api/Survey/survey-definitions/{surveyId}Request bodyRequiredRejected
POST /api/Survey/survey-responseBody, as communityProjectIdOptionalThe response is not linked to any community project
GET /api/Survey/survey-definition/{id}AbsentScope comes from the survey definition itself
GET /api/Project/GetByMethodologyQueryRequired200 with an empty array
GET /api/KpiDefinition/GetByMethodologyQueryRequiredNothing, unless projectId is also sent — then 403 Forbidden
POST /api/KpiDefinition/SaveBody, as communityProjectIdOptionalThe definition is program-scoped or project-scoped instead
DELETE /api/Methodology/{communityId}/{id}Route segmentRequiredCannot be omitted — the route does not match
GET /api/Community/{id}/ApplicationDefinitionsRoute segmentRequiredCannot be omitted — the route does not match
POST /api/ApplicationDefinitionRequest bodyRequiredTreated as community 0, and the community lookup fails
GET /api/ApplicationDefinition/{id}AbsentDerived from the application definition
POST /api/apikey, GET /api/apikeyAbsentAPI keys belong to a user, not a community