Project resources
Resources are the files and links attached to a project. On this page we'll dive into the endpoints you use to list them, add them, remove them, and set the privacy level that decides who can see each one.
How resource privacy works
Every resource carries a privacy level. It decides who sees the resource: everyone who can already reach the project, the community's members, the project's team, the team plus its mentors, or only the circles you pick by hand. A community's administrators always see everything inside their own community.
A resource belongs to one of two scopes. A community-project resource belongs to one community's view of a project — it is what you get when you add a resource while working inside a community. A project resource belongs to the project itself and has no single owning community. The scope is fixed when the resource is created and never changes afterwards.
On top of its own privacy level, a community-project resource can be shared into other communities, each with its own independently chosen level: Team where it lives, say, and Custom with two named circles in a community you shared it with. Sharing never rewrites the resource's own level — the two are separate, and a viewer coming in from a community you shared with is governed by that share's level rather than the original.
Privacy levels
privacyLevel is sent as an integer, both for a resource's own level and for each share.
| Value | Level | Who can see the resource |
|---|---|---|
1 | Public | Anyone who can already reach the parent project or community. |
2 | Community | Every approved member of the community. |
3 | Team | The project's team only. |
4 | Custom | Only members of the circles you grant. |
5 | Team and mentors | The project's team together with its mentors. |
0 (undefined) and 6 (set by team) exist in the wider platform but are not valid for a resource — sending either is rejected. There is no default: a resource takes the level you give it when you create it.
Not every level fits every scope:
| Level | Community-project resource | Project resource | A share |
|---|---|---|---|
| Public | Yes | Yes | Yes |
| Community | Yes | No | Yes |
| Team | Yes | Yes | Yes |
| Team and mentors | Yes | Yes | Yes |
| Custom | Yes, with circles | Yes, with circles | Yes, with circles |
A share set to Community, Team or Team and mentors requires the project to actually exist in the community you are sharing into.
List a project's resources
This endpoint allows you to retrieve a project's resources, filtered to the ones you are allowed to see, along with the flags describing what you may do with them.
Request body attributes
- Name
projectId- Type
- integer
- Description
Required. The ID of the project whose resources you want.
- Name
communityId- Type
- integer | null
- Description
The community you are viewing the project from. This decides which resources are in scope and which privacy levels apply to you. Omit it for a project-wide view.
- Name
paragraphId- Type
- integer | null
- Description
Restricts the list to the resources attached to one program paragraph.
- Name
concept- Type
- string
- Description
Free-text search across the resources.
- Name
tags- Type
- array of string
- Description
Restricts the list to resources carrying any of these tag names.
- Name
orderBy- Type
- integer
- Description
Sort order:
0unordered,1most recent first.
- Name
skip- Type
- integer
- Description
The number of resources to skip. Defaults to
0.
- Name
take- Type
- integer
- Description
The maximum number of resources to return.
pageSizeis accepted as an alias.
Response attributes
- Name
canEditResources- Type
- boolean
- Description
Whether you may add and edit resources on this project.
- Name
canEditPrivacy- Type
- boolean
- Description
Whether you may change resource privacy on this project.
- Name
resources- Type
- object
- Description
The paginated result set:
countandlist. Described underresources.listarray items below.
- Name
paragraphId- Type
- integer | null
- Description
Echoes the
paragraphIdyou filtered by.
resources.list array items
- Name
id- Type
- integer
- Description
The ID of the resource.
- Name
name- Type
- string
- Description
The resource's display name.
- Name
description- Type
- string
- Description
The resource's description.
- Name
resourceUrl- Type
- string
- Description
The external link, for a link resource, or the stored path returned when the file was uploaded.
- Name
resourceType- Type
- integer
- Description
Detected from the file or URL:
0other,1image,2video,3PDF. Not something you set.
- Name
image- Type
- string
- Description
A preview image for the resource, where one could be generated.
- Name
icon- Type
- string
- Description
The icon identifier stored with the resource.
- Name
postDate- Type
- string
- Description
When the resource was added (ISO 8601).
- Name
lastUpdated- Type
- string
- Description
When the resource was last changed (ISO 8601).
- Name
resourceTags- Type
- array of string
- Description
The resource's tag names.
- Name
privacyLevel- Type
- integer
- Description
The resource's own privacy level.
- Name
effectivePrivacyLevel- Type
- integer
- Description
The level that actually governs your access to it — the resource's own level when you are in the community that owns it, or the applicable share's level when you are viewing from a community it was shared into.
- Name
originCommunityId- Type
- integer | null
- Description
The community the resource came from, set only when you are seeing it through a share.
nullotherwise.
- Name
originCommunityName- Type
- string | null
- Description
The name of that community.
- Name
currentlySharedWith- Type
- array
- Description
The communities the resource is shared into, each as
communityId,communityNameandprivacyLevel. Only populated for callers who may edit the resource; an empty array otherwise.
- Name
canEdit- Type
- boolean | null
- Description
Whether you may edit or delete this particular resource.
- Name
isProjectScoped- Type
- boolean
- Description
Whether the resource belongs to the project itself, with no owning community.
- Name
isCommunityProjectScoped- Type
- boolean
- Description
Whether the resource belongs to one community's view of the project.
- Name
projectId- Type
- integer | null
- Description
The project the resource belongs to.
- Name
communityProjectId- Type
- integer | null
- Description
The community-project the resource belongs to, for a community-project resource.
- Name
paragraphId- Type
- integer | null
- Description
The program paragraph the resource is attached to, if any.
Resources belonging to a community-project that has been disabled drop out of every list, in the owning community and in any community they were shared into, until it is enabled again. The shares themselves survive.
Request
curl -X POST https://api.babele.co/api/Project/GetResourceList \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJleGFtcGxlIiwiZXhwIjoxNzQzODY1MjA3fQ.DEMO_SIGNATURE_NOT_A_REAL_TOKEN" \
-H "Content-Type: application/json" \
-d '{"projectId":1714,"communityId":999,"skip":0,"take":20,"orderBy":1}'
Response
{
"canEditResources": true,
"canEditPrivacy": true,
"paragraphId": null,
"resources": {
"count": 2,
"list": [
{
"id": 123,
"name": "Q2 strategy deck",
"description": "Deck for the quarterly review.",
"resourceUrl": "resource_files/q2-strategy-deck_20260610101500.pdf",
"resourceType": 3,
"image": "resource_files/q2-strategy-deck_20260610101500_preview.png",
"icon": "pdf",
"postDate": "2026-06-10T10:15:00Z",
"lastUpdated": "2026-06-10T10:15:00Z",
"resourceTags": ["strategy"],
"privacyLevel": 3,
"effectivePrivacyLevel": 3,
"originCommunityId": null,
"originCommunityName": null,
"currentlySharedWith": [
{ "communityId": 1042, "communityName": "Impact Network", "privacyLevel": 3 }
],
"canEdit": true,
"isProjectScoped": false,
"isCommunityProjectScoped": true,
"projectId": 1714,
"communityProjectId": 200,
"paragraphId": null
},
{
"id": 187,
"name": "Pitch video",
"description": "",
"resourceUrl": "https://vimeo.com/example",
"resourceType": 2,
"image": "",
"icon": "link",
"postDate": "2026-05-02T08:41:00Z",
"lastUpdated": "2026-05-02T08:41:00Z",
"resourceTags": [],
"privacyLevel": 1,
"effectivePrivacyLevel": 1,
"originCommunityId": null,
"originCommunityName": null,
"currentlySharedWith": [],
"canEdit": true,
"isProjectScoped": true,
"isCommunityProjectScoped": false,
"projectId": 1714,
"communityProjectId": null,
"paragraphId": null
}
]
}
}
Upload a file
Adding a file resource is a two-step operation. First upload the file here; then create the resource with the path this endpoint returns. For a link resource, skip this step and put the external URL straight into resourceUrl.
This endpoint takes a multipart/form-data body and responds with the stored path as a JSON string. It does not create a resource on its own, and it sets no privacy.
Form fields
- Name
file- Type
- file
- Description
Required. The file to upload.
- Name
folder- Type
- string
- Description
The folder to store the file under. Use
resource_filesfor project resources.
Query parameters
- Name
isBigFile- Type
- boolean
- Description
Raises the size ceiling from 3 MB to 100 MB. Defaults to
false.
Accepted files
Uploads are restricted by extension and content type. The accepted extensions are .csv, .txt, .asf, .bmp, .doc, .docx, .flac, .gif, .ico, .jfif, .jpeg, .jpg, .mid, .midi, .mkv, .mp3, .mp4, .mpeg, .mpg, .msg, .odp, .ods, .odt, .oga, .ogg, .ogv, .pdf, .png, .ppt, .pptx, .psd, .tif, .tiff, .webm, .webp, .wma, .wmv, .woff, .woff2, .xls, .xlsx, .xml and .yaml.
Possible errors
- Name
413 Payload Too Large- Description
The file is over the ceiling for this request.
- Name
500 Internal Server Error- Description
The file's extension or content type is not accepted.
Request
curl -X POST "https://api.babele.co/api/File/Upload?isBigFile=false" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJleGFtcGxlIiwiZXhwIjoxNzQzODY1MjA3fQ.DEMO_SIGNATURE_NOT_A_REAL_TOKEN" \
-F "file=@q2-strategy-deck.pdf" \
-F "folder=resource_files"
Response
"resource_files/q2-strategy-deck_20260610101500.pdf"
Add or update a project resource
This endpoint allows you to attach a file or a link to a project, and to edit one you have already added. Send an id of 0 to create; send an existing ID to update. It responds with the saved resource.
Project team members can add resources to their project. Inside a community, so can the project's mentors and the community's administrators.
Choosing the scope
Send exactly one of these three shapes. An update never moves a resource between scopes — the scope it was created with always wins.
- Name
communityProjectId- Description
The community-project this resource belongs to. Creates a community-project resource.
- Name
projectId and communityId- Description
The same thing, named the long way round.
- Name
projectId alone- Description
Creates a project resource, belonging to the project with no owning community. Send
0forcommunityProjectIdandcommunityId.
Request body attributes
- Name
id- Type
- integer
- Description
Required.
0to create a new resource, or the ID of the one you are updating.
- Name
name- Type
- string
- Description
Required. The resource's display name.
- Name
description- Type
- string
- Description
A description of the resource.
- Name
resourceUrl- Type
- string
- Description
Required. The external link, or the path returned by
POST /api/File/Upload.
- Name
privacyLevel- Type
- integer
- Description
Required. Who can see the resource. See Privacy levels above — there is no default, and
0and6are rejected.2(Community) is not valid on a project resource.
- Name
icon- Type
- string
- Description
An icon identifier to show with the resource.
- Name
resourceTags- Type
- array of string
- Description
Tag names for the resource.
- Name
projectId- Type
- integer
- Description
The project the resource belongs to. See Choosing the scope above.
- Name
communityProjectId- Type
- integer
- Description
The community-project the resource belongs to.
0for a project resource.
- Name
communityId- Type
- integer
- Description
The community the resource belongs to.
0for a project resource.
- Name
paragraphId- Type
- integer | null
- Description
Attaches the resource to a program paragraph. When set, the paragraph decides the scope and the other scope fields are ignored.
This endpoint sets the resource's own privacy level only. Granting circles
for a Custom level, and sharing the resource into other communities, are
done through POST /api/Privacy/SaveResourcePrivacy below.
A resource added by one of the project's mentors is always created as Custom, visible to the team and mentors, whatever level was asked for.
Possible errors
- Name
400 Bad Request- Description
The scope fields do not form one of the three valid shapes, or
privacyLevelis not valid for that scope.
- Name
403 Forbidden- Description
You may not add or edit resources on this project.
Request
curl -X POST https://api.babele.co/api/Resource/SaveProjectResource \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJleGFtcGxlIiwiZXhwIjoxNzQzODY1MjA3fQ.DEMO_SIGNATURE_NOT_A_REAL_TOKEN" \
-H "Content-Type: application/json" \
-d '{"id":0,"name":"Q2 strategy deck","description":"Deck for the quarterly review.","resourceUrl":"resource_files/q2-strategy-deck_20260610101500.pdf","privacyLevel":3,"icon":"pdf","resourceTags":["strategy"],"projectId":1714,"communityProjectId":200,"communityId":999,"paragraphId":null}'
Response
{
"id": 123,
"name": "Q2 strategy deck",
"description": "Deck for the quarterly review.",
"resourceUrl": "resource_files/q2-strategy-deck_20260610101500.pdf",
"resourceType": 3,
"icon": "pdf",
"postDate": "2026-06-10T10:15:00Z",
"lastUpdated": "2026-06-10T10:15:00Z",
"resourceTags": ["strategy"],
"privacyLevel": 3,
"effectivePrivacyLevel": 3,
"currentlySharedWith": [],
"canEdit": true,
"isProjectScoped": false,
"isCommunityProjectScoped": true,
"projectId": 1714,
"communityProjectId": 200,
"paragraphId": null
}
Remove a project resource
This endpoint allows you to delete a project resource, together with its uploaded file.
This endpoint mutates data over GET, which is a backend convention rather
than a mistake on your side. There is no DELETE equivalent.
Deleting is permanent, and it takes the resource's circle grants and every share on it with it — the communities you had shared it into lose access immediately.
Query parameters
- Name
id- Type
- integer
- Description
Required. The ID of the resource to delete.
Possible errors
- Name
403 Forbidden- Description
You may not delete this resource.
Request
curl -X GET "https://api.babele.co/api/Resource/RemoveProjectResource?id=123" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJleGFtcGxlIiwiZXhwIjoxNzQzODY1MjA3fQ.DEMO_SIGNATURE_NOT_A_REAL_TOKEN"
Response
{
"statusCode": 200
}
Get a resource's privacy
This endpoint allows you to read everything behind a resource's privacy: its own level and granted circles, every share on it, and the communities you could share it into next.
What comes back is scoped to you. The project's team and the owning community's administrators see every share and every candidate. An administrator of a community the resource was shared into sees their own community's share. Someone who can only read the resource sees empty shares and shareCandidates — they can open the resource without learning who else can.
Query parameters
- Name
resourceId- Type
- integer
- Description
Required. The ID of the resource.
Response attributes
- Name
resourceId- Type
- integer
- Description
The ID of the resource.
- Name
isProjectScoped- Type
- boolean
- Description
Whether the resource belongs to the project itself rather than to one community's view of it.
- Name
owningCommunityId- Type
- integer | null
- Description
The community that owns the resource.
nullfor a project resource.
- Name
owningCommunityName- Type
- string | null
- Description
The name of that community.
- Name
owner- Type
- object
- Description
The resource's own privacy:
privacyLevel, pluscircleswhen that level is4(Custom). Described undercirclesarray items below.
- Name
shares- Type
- array
- Description
One entry per share you are allowed to see, each with
communityId,communityName,privacyLevelandcircles.
- Name
shareCandidates- Type
- array
- Description
The communities you could share this resource into, each as
communityIdandcommunityName.
- Name
canEdit- Type
- boolean
- Description
Whether you may change the resource's own privacy.
- Name
canShareCrossCommunity- Type
- boolean
- Description
Whether you may add, change or remove shares.
circles array items
Circles are returned grouped by where they come from. Groups are only populated for a Custom level, and they list the circles actually granted.
- Name
name- Type
- string
- Description
The name of the group — the project or the community the circles belong to.
- Name
isProject- Type
- boolean
- Description
Whether this group holds project circles.
- Name
isCommunity- Type
- boolean
- Description
Whether this group holds community circles.
- Name
privacyCircles- Type
- array
- Description
The granted circles, each with
id,name,longName,isActive,projectIdandcommunityId.
Request
curl -X GET "https://api.babele.co/api/Privacy/GetResourcePrivacy?resourceId=123" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJleGFtcGxlIiwiZXhwIjoxNzQzODY1MjA3fQ.DEMO_SIGNATURE_NOT_A_REAL_TOKEN" \
-H "Content-Type: application/json"
Response
{
"resourceId": 123,
"isProjectScoped": false,
"owningCommunityId": 999,
"owningCommunityName": "Acme Accelerator",
"owner": {
"privacyLevel": 4,
"circles": [
{
"name": "Acme Accelerator",
"isProject": false,
"isCommunity": true,
"privacyCircles": [
{
"id": 22,
"name": "Members",
"longName": "Acme Accelerator: Members",
"isActive": true,
"projectId": null,
"communityId": 999
}
]
}
]
},
"shares": [
{
"communityId": 1042,
"communityName": "Impact Network",
"privacyLevel": 3,
"circles": []
}
],
"shareCandidates": [
{ "communityId": 1188, "communityName": "Climate Coalition" }
],
"canEdit": true,
"canShareCrossCommunity": true
}
Set a resource's privacy
This endpoint allows you to change a resource's own privacy level, its granted circles, and the communities it is shared into — in one call, applied together. It responds with an empty body; read the resource's privacy back to see the result.
Each block is optional and independent. Leave owner out to change only the shares; send only sharesToRemove to withdraw one. Circles are expressed as additions and removals rather than as a full list, so you never have to resend the grants you are not touching.
Request body attributes
- Name
resourceId- Type
- integer
- Description
Required. The ID of the resource.
- Name
owner- Type
- object
- Description
The resource's own privacy. Omit to leave it untouched. Takes
privacyLevel,circlesToAddandcirclesToRemove.
- Name
sharesToUpsert- Type
- array
- Description
The shares to create or update. Each item takes
communityId,privacyLevel,circlesToAddandcirclesToRemove.
- Name
sharesToRemove- Type
- array
- Description
The shares to withdraw, each as an object with a
communityId. Removing a share that is not there is not an error.
circlesToAdd and circlesToRemove array items
- Name
circleId- Type
- integer
- Description
The ID of the circle to grant or revoke.
- Name
projectId- Type
- integer | null
- Description
Set this for a project circle, and leave
communityIdnull.
- Name
communityId- Type
- integer | null
- Description
Set this for a community circle, and leave
projectIdnull.
A circle belonging to a community other than the one that owns the
resource goes in that community's share block, never in owner. Putting
one in owner.circlesToAdd is rejected with 400 Bad Request.
Moving a block off Custom clears the circles it had granted. The share itself survives a level change — an empty Custom share stays until you remove it explicitly.
Who may change what
- Name
The resource's own privacy- Description
The project's team, and — for a community-project resource — the owning community's administrators.
- Name
Adding or updating a share- Description
For a community-project resource, the owning community's administrators. For a project resource, the project's team, into any community the project belongs to.
- Name
Removing a share- Description
The project's team, and the administrators of the community being unshared, who can always withdraw a resource from their own community.
Possible errors
- Name
400 Bad Request- Description
A privacy level that is not valid for that block, a share level of
Community,TeamorTeam and mentorsfor a community the project does not belong to, or a foreign community's circle in theownerblock.
- Name
403 Forbidden- Description
You may not change this part of the resource's privacy.
- Name
409 Conflict- Description
A share for that community already exists and is not yours to change.
Request
curl -X POST https://api.babele.co/api/Privacy/SaveResourcePrivacy \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJleGFtcGxlIiwiZXhwIjoxNzQzODY1MjA3fQ.DEMO_SIGNATURE_NOT_A_REAL_TOKEN" \
-H "Content-Type: application/json" \
-d '{"resourceId":123,"owner":{"privacyLevel":4,"circlesToAdd":[{"circleId":22,"communityId":999,"projectId":null}],"circlesToRemove":[]},"sharesToUpsert":[{"communityId":1042,"privacyLevel":3,"circlesToAdd":[],"circlesToRemove":[]}],"sharesToRemove":[{"communityId":1188}]}'
Response
200 OK
Unshare a resource from a community
This endpoint allows you to withdraw a single share, without assembling a full privacy update. It is the same operation as sending one sharesToRemove entry above, and it responds with an empty body.
Request body attributes
- Name
resourceId- Type
- integer
- Description
Required. The ID of the resource.
- Name
communityId- Type
- integer
- Description
Required. The community to withdraw the resource from.
Possible errors
- Name
403 Forbidden- Description
You may not remove this share.
Request
curl -X POST https://api.babele.co/api/Privacy/UnshareResourceFromCommunity \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJleGFtcGxlIiwiZXhwIjoxNzQzODY1MjA3fQ.DEMO_SIGNATURE_NOT_A_REAL_TOKEN" \
-H "Content-Type: application/json" \
-d '{"resourceId":123,"communityId":1042}'
Response
200 OK
