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.

ValueLevelWho can see the resource
1PublicAnyone who can already reach the parent project or community.
2CommunityEvery approved member of the community.
3TeamThe project's team only.
4CustomOnly members of the circles you grant.
5Team and mentorsThe 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:

LevelCommunity-project resourceProject resourceA share
PublicYesYesYes
CommunityYesNoYes
TeamYesYesYes
Team and mentorsYesYesYes
CustomYes, with circlesYes, with circlesYes, 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.


POST/api/Project/GetResourceList

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: 0 unordered, 1 most 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. pageSize is 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: count and list. Described under resources.list array items below.

  • Name
    paragraphId
    Type
    integer | null
    Description

    Echoes the paragraphId you 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: 0 other, 1 image, 2 video, 3 PDF. 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. null otherwise.

  • 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, communityName and privacyLevel. 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.

Request

POST
/api/Project/GetResourceList
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
        }
    ]
}
}

POST/api/File/Upload

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_files for 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

POST
/api/File/Upload
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"

POST/api/Resource/SaveProjectResource

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 0 for communityProjectId and communityId.

Request body attributes

  • Name
    id
    Type
    integer
    Description

    Required. 0 to 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 0 and 6 are 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. 0 for a project resource.

  • Name
    communityId
    Type
    integer
    Description

    The community the resource belongs to. 0 for 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.

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 privacyLevel is not valid for that scope.

  • Name
    403 Forbidden
    Description

    You may not add or edit resources on this project.

Request

POST
/api/Resource/SaveProjectResource
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
}

GET/api/Resource/RemoveProjectResource?id={id}

Remove a project resource

This endpoint allows you to delete a project resource, together with its uploaded file.

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

GET
/api/Resource/RemoveProjectResource?id={id}
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/api/Privacy/GetResourcePrivacy?resourceId={resourceId}

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. null for 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, plus circles when that level is 4 (Custom). Described under circles array items below.

  • Name
    shares
    Type
    array
    Description

    One entry per share you are allowed to see, each with communityId, communityName, privacyLevel and circles.

  • Name
    shareCandidates
    Type
    array
    Description

    The communities you could share this resource into, each as communityId and communityName.

  • 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, projectId and communityId.

Request

GET
/api/Privacy/GetResourcePrivacy?resourceId={resourceId}
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
}

POST/api/Privacy/SaveResourcePrivacy

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, circlesToAdd and circlesToRemove.

  • Name
    sharesToUpsert
    Type
    array
    Description

    The shares to create or update. Each item takes communityId, privacyLevel, circlesToAdd and circlesToRemove.

  • 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 communityId null.

  • Name
    communityId
    Type
    integer | null
    Description

    Set this for a community circle, and leave projectId null.

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, Team or Team and mentors for a community the project does not belong to, or a foreign community's circle in the owner block.

  • 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

POST
/api/Privacy/SaveResourcePrivacy
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

POST/api/Privacy/UnshareResourceFromCommunity

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

POST
/api/Privacy/UnshareResourceFromCommunity
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