How to Add Image to PDF in Salesforce Apex using PDF.co

In this step-by-step guide, we’ll briefly see the procedure for adding images to PDF in Salesforce Apex using PDF.co. To start, we will also go through all the basic steps of PDF.co Salesforce integration. We will also provide the code and a video demonstration. Let’s get started!

Step 1: Create Remote Site Settings

Create two remote site settings in the Salesforce Org like below:

Remote Site Settings

Please note that the URL is “https://api.pdf.co”.

Remote Site URL

Please note that the URL is “https://pdf-temp-files.s3.amazonaws.com”.

Step 2: Create Apex Class in Salesforce

Create an apex class in Salesforce like below and paste the code there.
Once you login to the Salesforce org, you will see the screen like below and click on “Developer Console”

Remote Site Edit

Create an apex class. For this, click on “Files” then “New” then “Apex Class”.

Apex Class

Write the class name “AddImageToTheExistingPDF” and click “Ok”. Now copy the AddImageToTheExistingPDF code in this file.

Similarly, create a new file with the name “AddImageToTheExistingPDFTest” and copy the code.

Step 3: Add the API Key

In the AddImageToTheExistingPDF file, please add your API key by replacing the ‘******************************************’;.

Add API Key

Step 4: Verify the Code

To Verify the code, please open the execute Anonymous window and call the method like below.

Verify Code
Verify Code

Then Click on “Execute”.

Step 5: Search Files

Now, Search Files from the “App Launcher”.

Search Files

You will see the resulting PDF file there.

Step 6: Source Code Files

AddImageToTheExistingPDF.cls

public class AddImageToTheExistingPDF {
    
    public static void addImageToPDF()
    {
        String API_KEY = '*****************************************';        
        string SourceFileUrl = 'https://bytescout-com.s3.amazonaws.com/files/demo-files/cloud-api/pdf-edit/sample.pdf';
        string Pages = '';
        string Password = '';
        String DestinationFile = 'result';

        string Type1  = 'image';
        Integer X = 400;
        Integer Y = 600;
        Integer Width1  = 119;
        Integer Height1  = 32;
        String ImageUrl = 'https://bytescout-com.s3.amazonaws.com/files/demo-files/cloud-api/pdf-edit/logo.png';


        Map<string, Object> parameters = new Map<string, Object>();
        parameters.put('name', DestinationFile);
        parameters.put('password', Password);
        parameters.put('pages', Pages);
        parameters.put('url', SourceFileUrl);
        parameters.put('type', Type1);
        parameters.put('x', X);
        parameters.put('y', Y);
        parameters.put('width', Width1);
        parameters.put('height', Height1);
        parameters.put('urlimage', ImageUrl);
        
        string jsonPayload = Json.serialize(parameters);
        try
        {
            string url = 'https://api.pdf.co/v1/pdf/edit/add';
            HttpRequest req = new HttpRequest();
            req.setBody(jsonPayload);
            req.setHeader('x-api-key', API_KEY);
            req.setHeader('Content-Type', 'application/json');
            req.setEndpoint(url);
            req.setMethod('POST');
            req.setTimeout(60000);
            Http http = new Http();
            HTTPResponse res = http.send(req);
            if(res.getStatusCode() == 200) 
            {
                System.Debug('res ' + res);
                Map<String, Object> deserializedBody =  (Map<String, Object>)JSON.deserializeUntyped(res.getBody());
                String urlVal = (String)deserializedBody.get('url');
                downloadPDFAndStore(urlVal, DestinationFile);
            }
            else
            {
                System.debug('Success Response ' + res.getBody());
                System.Debug(' Status ' + res.getStatus());
                System.Debug(' Status Code' + res.getStatusCode());
                System.Debug(' Status String' + res.toString());
            }
           
        }
        catch(Exception ex)
        {
            String errorBody = 'Message: ' + ex.getMessage() + ' -- Cause: ' + ex.getCause() + ' -- Stacktrace: ' + ex.getStackTraceString();
            System.Debug(errorBody);
        }
    }

    @TestVisible
    private static void downloadPDFAndStore(String extFileUrl, String DestinationFile)
    {
        try
        {
            Http h = new Http(); 
            HttpRequest req = new HttpRequest(); 
            extFileUrl = extFileUrl.replace(' ', '%20'); 
            req.setEndpoint(extFileUrl); 
            req.setMethod('GET'); 
            req.setHeader('Content-Type', 'application/pdf'); 
            req.setCompressed(true); 
            req.setTimeout(60000); 
            //Now Send HTTP Request
            HttpResponse res  = h.send(req); 
            if(res.getStatusCode() == 200) 
            {
                blob fileContent = res.getBodyAsBlob();
                ContentVersion conVer = new ContentVersion();
                conVer.ContentLocation = 'S'; // to use S specify this document is in Salesforce, to use E for external files
                conVer.PathOnClient = DestinationFile + '.pdf'; // The files name, extension is very important here which will help the file in preview.
                conVer.Title = DestinationFile; // Display name of the files
                conVer.VersionData = fileContent;
                insert conVer;
                System.Debug('Success');
            }
            else
            {
                System.debug('Success Response ' + res.getBody());
                System.Debug(' Status ' + res.getStatus());
                System.Debug(' Status Code' + res.getStatusCode());
                System.Debug(' Status String' + res.toString());
            }
        }
        catch(Exception ex)
        {
            String errorBody = 'Message: ' + ex.getMessage() + ' -- Cause: ' + ex.getCause() + ' -- Stacktrace: ' + ex.getStackTraceString();
            System.Debug(errorBody);
        }
    }
}

AddImageToTheExistingPDFTest.cls

@isTest
public class AddImageToTheExistingPDFTest
{
    private  testmethod static void testaddImageToPDF()
    {
        Test.setMock(HttpCalloutMock.class, new AddImageToTheExistingPDFTest.DocumentCreationMock());
        AddImageToTheExistingPDF.addImageToPDF();
        List cv = [select Id from ContentVersion];
        System.assertEquals(1, cv.size());
    }

    private  testmethod static void testFetchDataAndCreatePDFException()
    {
        AddImageToTheExistingPDF.addImageToPDF();
        List cv = [select Id from ContentVersion];
        System.assertEquals(0, cv.size());
    }
    
    private  testmethod static void testdownloadPDFAndStoreException()
    {
        AddImageToTheExistingPDF.downloadPDFAndStore(null, null);
        List cv = [select Id from ContentVersion];
        System.assertEquals(0, cv.size());
    }

    public class DocumentCreationMock implements HttpCalloutMock {
        public HTTPResponse respond(HTTPRequest req) {
            HttpResponse res = new HttpResponse();
            String testBody = '{"hash":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","url":"https://pdf-temp-files.s3-us-west-2.amazonaws.com/0c336bfcef1a473d98492bda25d8da03/newDocument.pdf?X-Amz-Expires=3600&x-amz-security-token=FwoGZXIvYXdzEO7%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaDHWK1dY4d4lOgsheliKBATwE%2FZewASPTEnPxTn%2BOdYhP4h3gljAJfqbRvQptDX7wdWLmrBS7Tg4qTU6pAbxIdXChGPjBWpSbtiADJKmqkmyhkUmE8GSM1%2FGtJO6bga2pgzvFLXmzxjTf3%2BFNqwYOvbyApIZdVLoPpEKY6PlCflQtLTd30dhelm6xpB8pitbdhSjdz8KCBjIobVy%2Fjwybwp6OQgB%2FT6QkIo2dU07gtFREdn5jhRyvnS5lkccweBV1%2Bw%3D%3D&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIA4NRRSZPHMV5P3JOS/20210316/us-west-2/s3/aws4_request&X-Amz-Date=20210316T124309Z&X-Amz-SignedHeaders=host;x-amz-security-token&X-Amz-Signature=95287bf3c007fed4c2c5aeea1ce75c846cc6c68b22aaf35175ebe41a105f54e1","pageCount":1,"error":false,"status":200,"name":"newDocument","remainingCredits":9913694,"credits":3}';
            res.setHeader('Content-Type', 'application/json');
            res.setBody(testBody);
            res.setStatusCode(200);
            return res;
        }
    }
}

Video Guide