I have created a rest API that returns the list of opportunities as well as files attached to the opportunities. I am able to call the API and retrieve the data via POSTMAN. This is the code:

global with sharing class GetOpportunities {
    global static List<sObject> doGet() {
        RestRequest req = RestContext.request;
        RestResponse res = RestContext.response;

        List<sObject> result=new List<sObject>();

        List<sObject> opps = [
            Select Id, Name, ........
            FROM Opportunity
            WHERE RecordType.Name = 'Test' AND
            StageName = 'XYZ' 

        Set<Id> contentDocIds = new Set<Id>();
        for (ContentDocumentLink cdl : [
            SELECT id, LinkedEntityId, ContentDocumentId 
            FROM ContentDocumentLink 
            WHERE LinkedEntityId IN (
                SELECT Id 
                FROM Opportunity 
                WHERE StageName = 'XYZ'
        ]) {

        List<sObject> cvList = [
            select id, Checksum, ContentBodyId, 
                ContentDocumentId, ContentLocation, ContentModifiedById,
                ContentModifiedDate, ContentSize, ContentUrl, Description, 
                ExternalDataSourceId, ExternalDocumentInfo1,
                ExternalDocumentInfo2, FeaturedContentBoost, FeaturedContentDate, 
                FileExtension, FileType, FirstPublishLocationId, IsAssetEnabled, 
                IsLatest,IsMajorVersion, NegativeRatingCount,  Origin, OwnerId, PathOnClient, 
                PositiveRatingCount, PublishStatus, RatingCount, ReasonForChange, 
                SharingOption,SharingPrivacy, TagCsv, TextPreview, Title, VersionNumber, 
            FROM ContentVersion 
            WHERE ContentDocumentId IN :contentDocIds

        return result;


The versiondata gives me some link right now e.g. /services/data/v47.0/sobjects/ContentVersion/0686C0000000i9OQAQ/VersionData

How do I convert it to actual content? I need the actual file e.g. pdf, ppt, jpg e.t.c.


1 Answer 1


Your external caller needs to make an additional REST call to the URL given for the VersionData of each ContentVersion, i.e., <your Salesforce domain>/services/data/v47.0/sobjects/ContentVersion/0686C0000000i9OQAQ/VersionData.

Your caller would make one request per file to retrieve the data for each file individually.

  • Yes but let's say if there were 50-200 files/links to files retrieved in the first request. Would it be feasible for the caller to make another 200 requests afterwards just to retrieve the content? Would there be any system.limit issues or API call issues?
    – Anonymous
    Oct 2, 2019 at 19:28
  • @Anonymous There could be, although that limit is fairly high relative to many other limits. I don't see that you have a lot of other options, though. You're not going to be able to bundle up 200 files and return that data without hitting the heap limit in a lot of cases.
    – David Reed
    Oct 2, 2019 at 19:46
  • ok if I go that route, is there a way by which the external caller/code instead of calling individual file link and getting the content, send the list of file links received in the first request at once and get their contents. That way they will only have to make one additional call. Do I have to create any additional get method in my REST API that could accept a list of urls and return their content somehow. I don't know what do you suggest? Can the number of calls be reduced somehow?
    – Anonymous
    Oct 2, 2019 at 20:30
  • @Anonymous Why are you worried about the number of calls made by the remote system? In most contexts, Salesforce/Apex CPU time and heap are far more limited resources than some arbitrary off-platform system. In any case, what you need to be calling is Sobject Blob Retrieve. I don't know offhand if it's supported by the Sobject Composite resource but I rather doubt it since it returns raw binary content.
    – David Reed
    Oct 2, 2019 at 20:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .