Set up your own APEX API source & test it with Postman

Set up your own APEX API source & test it with Postman

A few of my junior colleagues struggled to figure out where to start with Salesforce API testing. So, I put together this simple step-by-step guide to help them, as well as you, to set up your own APEX REST API in Salesforce. I’ll also show you how to test it using Postman. By the time you finish reading this article, you’ll have a fully functional APEX REST API and know how to interact securely and efficiently, ensuring everything works smoothly before you integrate it.

APEX Code for Postman API testing

You have to set up the following APEX code in your Salesforce Developer Console:

@RestResource(urlMapping='/exampleEndpoint/*')
global with sharing class MyCustomAPI {

    // Utility Method for Pretty JSON Formatting
    private static String prettyPrint(String jsonString) {
        jsonString = jsonString.replace('{', '{\n  ');
        jsonString = jsonString.replace('}', '\n}');
        jsonString = jsonString.replace(',', ',\n  ');
        jsonString = jsonString.replace('[', '[\n  ');
        jsonString = jsonString.replace(']', '\n]');
        return jsonString;
    }

    // Utility Method for Error Responses
    private static String errorResponse(String message, Integer statusCode) {
        RestContext.response.statusCode = statusCode;
        Map<String, String> error = new Map<String, String>();
        error.put('error', message);
        return prettyPrint(JSON.serialize(error));
    }

    // REST API GET Method
    @HttpGet
    global static void getExampleDataREST() {
        RestRequest req = RestContext.request;
        RestResponse res = RestContext.response;

        String recordId = req.requestURI.substring(req.requestURI.lastIndexOf('/') + 1);

        if (String.isNotBlank(recordId)) {
            try {
                Account acc = [SELECT Id, Name FROM Account WHERE Id = :recordId LIMIT 1];
                String prettyJsonResponse = JSON.serializePretty(acc);

                res.statusCode = 200; // HTTP 200 OK
                res.addHeader('Content-Type', 'application/json');
                res.responseBody = Blob.valueOf(prettyJsonResponse);
            } catch (Exception e) {
                res.statusCode = 404; // Not Found
                res.responseBody = Blob.valueOf('{"error": "Record not found"}');
            }
            return;
        }

        res.statusCode = 400; // Bad Request
        res.responseBody = Blob.valueOf('{"error": "No specific record requested"}');
    }

    // REST API POST Method
    @HttpPost
    global static void createExampleDataREST() {
        RestRequest req = RestContext.request;
        RestResponse res = RestContext.response;

        try {
            Account acc = (Account) JSON.deserialize(req.requestBody.toString(), Account.class);

            // Validate required fields
            if (String.isBlank(acc.Name)) {
                res.statusCode = 400; // Bad Request
                res.responseBody = Blob.valueOf('{"error": "Account Name is required"}');
                return;
            }

            insert acc;

            // Create a response map
            Map<String, Object> response = new Map<String, Object>();
            response.put('Id', acc.Id);
            response.put('Name', acc.Name);

            // Pretty print JSON
            String prettyJsonResponse = JSON.serializePretty(response);

            // Set response headers and body
            res.statusCode = 201; // HTTP 201 Created
            res.addHeader('Content-Type', 'application/json');
            res.responseBody = Blob.valueOf(prettyJsonResponse);
        } catch (Exception e) {
            res.statusCode = 500; // Internal Server Error
            res.responseBody = Blob.valueOf('{"error": "Failed to create record: ' + e.getMessage() + '"}');
        }
    }

    // REST API PUT Method
    @HttpPut
    global static void updateExampleDataREST() {
        RestRequest req = RestContext.request;
        RestResponse res = RestContext.response;
        String recordId = req.requestURI.substring(req.requestURI.lastIndexOf('/') + 1);

        if (String.isNotBlank(recordId)) {
            try {
                Account existingAcc = [SELECT Id, Name FROM Account WHERE Id = :recordId LIMIT 1];
                Account updatedAcc = (Account) JSON.deserialize(req.requestBody.toString(), Account.class);

                // Validate required fields
                if (String.isBlank(updatedAcc.Name)) {
                    res.statusCode = 400; // Bad Request
                    res.responseBody = Blob.valueOf(prettyPrint(JSON.serialize(new Map<String, String>{
                        'error' => 'Account Name is required'
                    })));
                    return;
                }

                // Preserve the ID and update the record
                updatedAcc.Id = existingAcc.Id;
                update updatedAcc;

                // Create a response map
                Map<String, Object> response = new Map<String, Object>{
                    'Id' => updatedAcc.Id,
                    'Name' => updatedAcc.Name
                };

                // Use the custom prettyPrint utility for formatting
                String prettyJsonResponse = prettyPrint(JSON.serialize(response));

                res.statusCode = 200; // HTTP 200 OK
                res.addHeader('Content-Type', 'application/json');
                res.responseBody = Blob.valueOf(prettyJsonResponse);
            } catch (Exception e) {
                res.statusCode = 404; // Not Found
                res.responseBody = Blob.valueOf(prettyPrint(JSON.serialize(new Map<String, String>{
                    'error' => 'Failed to update record: ' + e.getMessage()
                })));
            }
            return;
        }

        res.statusCode = 400; // Bad Request
        res.responseBody = Blob.valueOf(prettyPrint(JSON.serialize(new Map<String, String>{
            'error' => 'No record ID provided for update'
        })));
    }

    // REST API DELETE Method
    @HttpDelete
    global static void deleteExampleDataREST() {
        RestRequest req = RestContext.request;
        RestResponse res = RestContext.response;
        String recordId = req.requestURI.substring(req.requestURI.lastIndexOf('/') + 1);

        if (String.isNotBlank(recordId)) {
            try {
                Account acc = [SELECT Id FROM Account WHERE Id = :recordId LIMIT 1];
                delete acc;

                res.statusCode = 204; // HTTP 204 No Content
                res.addHeader('Content-Type', 'application/json');
                res.responseBody = Blob.valueOf(prettyPrint(JSON.serialize(new Map<String, String>{
                    'message' => 'Record successfully deleted'
                })));
            } catch (Exception e) {
                res.statusCode = 404; // Not Found
                res.responseBody = Blob.valueOf(prettyPrint(JSON.serialize(new Map<String, String>{
                    'error' => 'Failed to delete record: ' + e.getMessage()
                })));
            }
            return;
        }

        res.statusCode = 400; // Bad Request
        res.responseBody = Blob.valueOf(prettyPrint(JSON.serialize(new Map<String, String>{
            'error' => 'No record ID provided for deletion'
        })));
    }
}

This code will allow you to dynamically update the Accounts Object record inside your Salesforce environment by using Postman requests.

How do you set up the Apex code for Salesforce?

First, you have to navigate to the Developers Console.
Then, click on File in the top left.
Inside it, click on New and select Apex Class.
You will be asked to provide a name for your Apex file.
After that, paste the Apex code I provided above into the newly created Apex file and save the changes.

Endpoints for Postman testing:

  • GET: Retrieve data about a single item by using its ID number
    /services/apexrest/exampleEndpoint/{id}
  • POST: Create a new item
    /services/apexrest/exampleEndpoint
    • Request body: { "Name": "New Account" }
  • PUT: Modify existing items name
    /services/apexrest/exampleEndpoint/{id}
    • Request body: { "Name": "Updated Account Name" }
  • DELETE: Delete an existing item
    /services/apexrest/exampleEndpoint/{id}

Real example showcase

After the APEX code has been updated in the Developers Console, we will start the testing procedure. We will need 2 instances open:

  • Open Postman
  • Open Accounts Object inside of Salesforce.
Empty Accounts Object. The updates made in Postman should be reflected here, including adding new items, changing them, and deleting them. When we create an item in Postman, it should also instantly appear in the Salesforce record. Same with all other requests.

Postman Request 0: Authentication

Before we make any request to our Accounts record, we should authenticate ourselves with Salesforce. I have already covered this step by implementing the SOAP method in my articles on SOAP Salesforce Authorization with Postman (no OAuth) and Automating Salesforce sessionId Retrieval in Postman for SOAP APIs. Check them out to set up the initial request.

Postman Request 1: Create an item

Request Type: POST
Path: https://fun-inspiration-5108.my.salesforce.com/services/apexrest/exampleEndpoint
Headers:
Authorization: Bearer {{sessionId}}

Body:

{ "Name": "First Account" }

Modify the value of the Name key on your own. Note that you can create multiple items, but you can do that 1 by one, so no numerous items at once. 1 item per request.

Response:

{
    "Name": "First Account",
    "Id": "001KB000006hgebYAA"
}

Postman Request 2: GET the item that we have just created

We are retrieving the item that we have just created by using its ID value.

Request Type: GET
Path: https://fun-inspiration-5108.my.salesforce.com/services/apexrest/exampleEndpoint/001KB000006hiDtYAI
Headers:
Authorization: Bearer {{sessionId}}

Body: None

Response:

{
    "attributes": {
        "type": "Account",
        "url": "/services/data/v62.0/sobjects/Account/001KB000006hiDtYAI"
    },
    "Id": "001KB000006hiDtYAI",
    "Name": "First Account"
}

Check the updated item in the Accounts Object from the Salesforce side

Refresh the record list, and the new item created should appear there with the same name that we had set for it in Postman.

Postman Request 3: Modify the name of the previously created item

Request Type: PUT
Path: https://fun-inspiration-5108.my.salesforce.com/services/apexrest/exampleEndpoint/001KB000006hiDtYAI
Headers:
Authorization: Bearer {{sessionId}}

Body:

{ "Name": "Updated Account Name" }

Request:

{
    "Name": "Updated Account Name",
    "Id": "001KB000006hiDtYAI"
}

Expected status: 200 OK

Postman Request 4: Check the change by sending another GET request

Request Type: GET
Path: https://fun-inspiration-5108.my.salesforce.com/services/apexrest/exampleEndpoint/001KB000006hiDtYAI
Headers:
Authorization: Bearer {{sessionId}}

Body: None

Response:

{
    "attributes": {
        "type": "Account",
        "url": "/services/data/v62.0/sobjects/Account/001KB000006hiDtYAI"
    },
    "Id": "001KB000006hiDtYAI",
    "Name": "Updated Account Name"
}

Expected status: 200 OK

Check if the new change is properly applied from the Salesforce side as well

After you refresh your items list, the previously created items should appear with the new name that was just updated.

Postman Request 5: Delete the item that was previously created

Request Type: DELETE
Path: https://fun-inspiration-5108.my.salesforce.com/services/apexrest/exampleEndpoint/001KB000006hiDtYAI
Headers:
Authorization: Bearer {{sessionId}}

Body: None

Response: Empty

Expected status: 204 No Content

Postman Request 6: Check if the item was deleted

Request Type: GET
Path: https://fun-inspiration-5108.my.salesforce.com/services/apexrest/exampleEndpoint/001KB000006hiDtYAI
Headers:
Authorization: Bearer {{sessionId}}

Body: None

Response: {“error”: “Record not found”}

Expected status: 404 Not Found

Check it from the Salesforce side as well!

Finally, once again, refresh the Accounts records list, and the previously created and updated item should now be removed following the Postman Request 5.

Scroll to Top