Synchronus Vs Asynchronus API's

API Vs Web Service

an API (Application Programming Interface) is a broader concept, while a web service is a specific type of API that operates over a network, typically the internet

API methods - Get, Put, Post, Delete

Put Vs Post

Advantages - Language independent, early defect identification

Protocols - HTTP, SOAP, REST(architectural pattern)

Tools - Postman, REST Assured

API documentation - quick ref for accessing library (Swagger)

Challenges - parameter selection, parameter combination, call sequence

Rest Vs RestAssured


API Codes

Informational codes - 100 Continue, 101 Switching Protocol, 102 Processing(WebDAV), 103 Early Hints

Status codes(success) - 200 OK(Success), 201 Created, 202 Accepted

Status codes(redirectional) - 301 Moved permanently, 302 Found

Client Side error codes - 400 Bad request, 401 Unauthorized, 403 Forbidden, 404 Not found, 429 Too may requests, 402 Payment  required(Experimental) -> Reserved for future user

Server side error codes - 500 internal server error, 501 Not implemented, 502 Bad gateway, 503 Service Unavailable, 504 Gateway timed out

Difference between 401 and 403

401 Unauthorized

Meaning:

→ You are not authenticated.

→ The server says: “You need to log in or provide credentials.”

Use Case:

No token sent

Invalid/missing API key

Not logged in

What to Do:

Log in or send proper credentials (e.g., Authorization header)


403 Forbidden

Meaning:

→ You are authenticated, but not authorized.

→ The server says: “You’re logged in, but not allowed to access this.”

Use Case:

User is logged in but lacks permission

Trying to access an admin-only page as a regular user

What to Do:

Contact admin or request access

Check role/permissions


Authentication methods - API Key, Basic authentication, Oauth, bearer token

  • Token-based authentication (Bearer token): This involves issuing a token to the client after successful authentication, which is then included in subsequent API requests for authorization.
  • API Key - application level
  • Basic authentication: This involves sending the username and password as part of the API request headers, encoded in base64 format.
  • OAuth: This is a widely used authorization framework that allows for delegating access rights from one entity to another without sharing credentials.

Sample API Programs

JSONArray_Query

package com.sample.pagefactory.api;


import org.json.JSONArray;

import org.json.JSONObject;


import io.restassured.RestAssured;

import io.restassured.response.Response;

import io.restassured.specification.RequestSpecification;


public class JSONArray_Query {

public static void main(String[] args)

{

RestAssured.baseURI = "https://demoqa.com/BookStore";

RequestSpecification request = RestAssured.given().auth()

                .preemptive().basic("username","password");

Response resp = request.get("/v1/Books");

String respBody = resp.getBody().asString();

System.out.println("Response Body:");

System.out.println(respBody);

JSONObject jsonObject = new JSONObject(respBody);

System.out.println("JSONObject:");

System.out.println(jsonObject);

System.out.println("JSONObject-Pretty print with 2-space indent:" );

System.out.println(jsonObject.toString(2)); // Pretty print with 2-space indent

JSONArray jsonArray = jsonObject.getJSONArray("books");

System.out.println("JSONArray:");

System.out.println(jsonArray);

System.out.println("First Item using get:");

System.out.println(jsonArray.get(0));

System.out.println("First Item using getJSONObject:");

System.out.println(jsonArray.getJSONObject(0));

for(int i=0;i<jsonArray.length();i++)

{

JSONObject obj = jsonArray.getJSONObject(i);

String author = obj.getString("author");

String title= obj.getString("title");

System.out.println(author + " - " +title);

if(author.contains("Addy Osmani"))

{

            System.out.println("SubTitle of Addy Osmani is:" +title);

}

}

}

    }


JSONPath_Query


package com.sample.pagefactory.api;


import java.util.HashMap;

import java.util.List;

import java.util.Map.Entry;


import io.restassured.RestAssured;

import io.restassured.response.Response;

import io.restassured.specification.RequestSpecification;

import io.restassured.path.json.JsonPath;


public class JSONPath_Query {


    public static void main(String[] args) {


        RestAssured.baseURI = "https://demoqa.com/BookStore";

        RequestSpecification request = RestAssured.given()

            .auth().preemptive().basic("username", "password");

        Response resp = request.get("/v1/Books");


        String respBody = resp.getBody().asString();

System.out.println("Response Body:");

System.out.println(respBody);


// JsonPath jsonPath = new JsonPath(respBody);

JsonPath jsonPath = resp.jsonPath();

List<HashMap<String, String>> data = jsonPath.getList("books");


System.out.println(" ");

System.out.println("Printing data using List");

System.out.println(" ");

for (HashMap<String, String> dataItem : data)

{

    System.out.println(dataItem.get("author"));

}


for (HashMap<String, String> dataItem : data)

        {

    if (dataItem.get("author").contains("Rechard"))

{

    System.out.println("Book written by Richard:"

                                    + dataItem.get("Title"));

}


}

        System.out.println(" ");

System.out.println("Printing data using hash map");

System.out.println(" ");


for (HashMap<String, String> dataItem : data)

        {

    for(Entry<String, String> entry : dataItem.entrySet())

                {

    if (entry.getKey().equals("author"))

                       {

    System.out.println(entry.getValue());

}

        }

        }

}

}


API_Get_JSONArray

package com.sample.pagefactory.api;


import org.json.JSONArray;

import org.json.JSONObject;

import org.testng.annotations.Test;


import io.restassured.RestAssured;

import io.restassured.response.Response;

import io.restassured.specification.RequestSpecification;



public class AP_Get_JSONArray {


@Test

public void ReadData() throws Exception {


RestAssured.baseURI = "https://demoqa.com/BookStore";

RequestSpecification request = RestAssured

.given()

// Basic Authentication

.auth()

.preemptive()

.basic("username", "password");

// .header("Authorization", "Bearer your_bearer_token_here") // Bearer Token

// .header("x-api-key", "your_api_key_here"); // API Key (custom header)

Response resp = request.get("/v1/Books");

String responseBody = resp.getBody().asString();

System.out.println("Raw Response as String: " + responseBody);

JSONObject jsonObject = new JSONObject(responseBody);

System.out.println("JSONObject:" +jsonObject.toString(2)); // Pretty print with 2-space indent

JSONArray dataArray = jsonObject.getJSONArray("books");

System.out.println("Data Array:" +dataArray);

System.out.println("first item: " +dataArray.getJSONObject(0));

System.out.println("first item: " +dataArray.get(0));

}

}


API_Get_JSONPath


package com.sample.pagefactory.api;


import java.util.HashMap;

import java.util.List;


import org.testng.Assert;

import org.testng.annotations.Test;

import io.restassured.RestAssured;

import io.restassured.http.Header;

import io.restassured.http.Headers;

import io.restassured.path.json.JsonPath;

import io.restassured.response.Response;

import io.restassured.specification.RequestSpecification;


public class API_Get_JSONPath {


    @Test

    public void testResponsecode()

{

// Response resp = RestAssured.get("https://reqres.in/api/users?page=1");


// Set the base URI

RestAssured.baseURI = "https://demoqa.com/BookStore";


// Build the request

RequestSpecification request = RestAssured.given()

// Basic Authentication

.auth().preemptive().basic("username", "password");

// .header("Authorization", "Bearer your_bearer_token_here") // Bearer Token

// .header("x-api-key", "your_api_key_here"); // API Key (custom header)


// Send GET request

Response response = request.get("/v1/Books");

int code = response.getStatusCode();

System.out.println(" Status code is " + code);


Assert.assertEquals(code, 200);


String responseBody = response.getBody().asString();

System.out.println("ResponseBody:" + responseBody);


// JsonPath jsonPath=response.jsonPath();

JsonPath jsonPath = new JsonPath(responseBody);

List<HashMap<String, String>> jsonData = jsonPath.getList("books");

System.out.println("json data:" + jsonData);


String contentType = response.header("Content-Type"); // same as response.getHeader("Content-type");

System.out.println("ContentType:" + contentType);


Headers allheaders = response.headers();

System.out.println(allheaders); // returns same output as response.getHeaders();

for (Header header : allheaders) // returns same output as above

{

System.out.println(header.getName() + ":" + header.getValue());

}

            }

        }


API_Get_JSONPath_Query


package com.sample.pagefactory.api;


import java.util.HashMap;

import java.util.List;


import org.testng.annotations.Test;

import io.restassured.RestAssured;

import io.restassured.path.json.JsonPath;

import io.restassured.response.Response;

import io.restassured.specification.RequestSpecification;


public class API_Get_JSONPath_QueryData {


@Test

public void ReadData() throws Exception {

// Response resp = RestAssured.get("https://demoqa.com/BookStore/v1/Books");

// Set the base URI

RestAssured.baseURI = "https://demoqa.com/BookStore";

// Build the request

RequestSpecification request = RestAssured

.given()

// Basic Authentication

.auth()

.preemptive()

.basic("username", "password");

// .header("Authorization", "Bearer your_bearer_token_here") // Bearer Token

// .header("x-api-key", "your_api_key_here"); // API Key (custom header)


// Send GET request

Response resp = request.get("/v1/Books");

System.out.println("Raw Response:" +resp);

System.out.println("Status Code: " + resp.getStatusCode());

String responseBody = resp.getBody().asString();

System.out.println("Raw Response as String: " + responseBody);

JsonPath jsonPath = resp.jsonPath();

// JsonPath jsonPath = new JsonPath(responseBody);


List<HashMap<String,String>> jsondata = jsonPath.getList("books");

System.out.println("jsondata:" +jsondata);

for(HashMap<String,String> item:jsondata)

{

if(item.get("title").equals("You Don't Know JS"))

{

System.out.println("author: " +item.get("author"));

         System.out.println("publisher: " +item.get("publisher"));

}

     }

for(HashMap<String,String> item:jsondata)

{

System.out.println(item.get("subTitle"));

}

}

}


API_Put


//https://toolsqa.com/rest-assured/post-request-using-rest-assured/

package com.sample.pagefactory.api;


import org.json.JSONObject;

import org.testng.annotations.Test;


import io.restassured.RestAssured;

import io.restassured.response.Response;

import io.restassured.specification.RequestSpecification;


public class API_Put {


@Test

public void PutAPIExample()

{

RestAssured.baseURI ="https://demoqa.com/Account/v1";

JSONObject requestParams = new JSONObject(); //in get request we need to pass response body as argument

requestParams.put("userName", "test_rest");

requestParams.put("password", "Testrest@123");

requestParams.put("id", 101);

requestParams.put("title", "Updated Title");

requestParams.put("author", "Updated Author");

// Build request with basic authentication

RequestSpecification request = RestAssured

.given()

// basic authentication

.auth()

.preemptive()

.basic("your_username", "your_password")

.header("Content-Type", "application/json")

// .header("Authorization", "Bearer your_bearer_token_here") --- bearer token

// .header("x-api-key", "your_api_key_here") --- api key

.body(requestParams.toString());

Response response = request.put("/books/101"); // Assuming REST path includes ID

System.out.println(response.getStatusLine());

System.out.println(response.getBody().asString());

}

}


API_Post


//https://toolsqa.com/rest-assured/post-request-using-rest-assured/


package com.sample.pagefactory.api;


import org.json.JSONObject;

import org.testng.annotations.Test;


import io.restassured.RestAssured;

import io.restassured.response.Response;

import io.restassured.specification.RequestSpecification;


public class API_Post {


@Test

public void api_test_2 ()

{

RestAssured.baseURI = "https://demoqa.com/BookStore/v1/Books";

JSONObject requestBody = new JSONObject(); //in get request we need to pass response body as argument 

requestBody.put("userId", "TQ123"); 

requestBody.put("isbn", "9781449325862"); 


RequestSpecification request = RestAssured.given();

request.auth().preemptive().basic("your_username", "your_password");

request.header("Content-Type", "application/json");

// request.header("Authorization", "Bearer your_token_here"); // to pass bearer token

// request.header("x-api-key", "your_api_key_here");  //api key 

request.body(requestBody.toString());

// Response response = request.queryParam("api_key", "your_api_key_here").post("/post"); // to pass api key


Response response = request.post("/users");

System.out.println("The status received: " + response.statusLine());

System.out.println("Status Code: " + response.getStatusCode());

System.out.println("Response Body: " + response.getBody().asString());

}

}


API_Delete


import io.restassured.RestAssured;

import io.restassured.response.Response;


public class DeleteRequestExample {

    public static void main(String[] args) {


        // Base URI of the API

        RestAssured.baseURI = "https://jsonplaceholder.typicode.com";


        // Send DELETE request to /posts/1

        Response response = RestAssured

            .given()

            .when()

            .delete("/posts/1");


        // Print response details

        System.out.println("Status Code: " + response.getStatusCode());

        System.out.println("Response Body: " + response.getBody().asString());

    }

}



Using HTTP request


import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;import java.io.IOException;public class DeleteRequestExample { public static void main(String[] args) throws IOException, InterruptedException { HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://httpbin.org/delete")) // Replace with your API endpoint .DELETE() .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println("Status Code: " + response.statusCode()); System.out.println("Response Body: " + response.body()); }}



Program 1

import org.testing.Assert;

import io.restassured.RestAssured;

import io.restassured.response.Response;

public class GetData

{

@Test

public void testResponsecode()

{

Response resp=RestAssured.get("https://reqres.in/api/users?page=2");

int code=resp.getStatusCode();,

System.out.printin(" Status code is "+code);

Assert.assertEquals(code, 200);

}


Program 2

Base URI = "";

RequestSpecification httprequest = RestAssured.given();

JSONObject requestparams = new JSONObject();

requestParams.put("Name", "xyx");

httpRequest.header("content-type", "application/json");

httpRequest.body(requestParams.toJSONString()); //payload

Response response = httprequest.request("Method.GET", "/hyderabad");

String responseBody = response.getBody.asString();


Put  - replaces entire resource, if the resource does not exist it can create it

Patch - applies partial modifications to a resource, updating only specified fields

Post - used for creating or appending resource

Json path  - query to retrieve data from JSON document

Json path parameter -


Specify base URI

  RestAssured.baseURI = "http://restpai.demoqa.com/utilities/weather/city";


Request Object

  RequestSpecification httpRequest =  RestAssured.given();


Response Object

  Response response = httprequest.request(Method.GET, "/Hyderabad");

  String responseBody = response.getBody().asString();

  int statusCode = response.getStatusCOde(); //200

  int responseTime = response.

  String statusLine = response.getStatusLine(); //HTTP/1.1 200 OK  


Request payload sending along with post request

  JSONObject requestParams = new JSONObject();

  requestParams.put("FirstName", "XYZ"); // payload  

  httpRequest.header("Content-Type", "application/json);  

  httpRequest.body(requestParams.toJSONString());

  Response response = httprequest.request(Method.POST, "/Hyderabad");

  String responseBody = response.getBody().asString();  

  String successCode = response.jsonPath().get("SuccessCode"); //OPERATION_SUCCESS


Capture details of headers from response  

  String respContentType = response.header("Content_Type")


Capture all the headers from response

  Headers allheaders = response.headers();

  for(Header header:allheaders)

  {

    s.o.p(header.getName()+" "+header.getValue());

  }


Verify the presence of a content in response body

  Assert.assertEquals(responseBody.contains("Delhi"), true)


Extract value of each node in JSON

  JsonPath jsonpath=response.jsonPath(); //extracts json portion of the response body  

  System.out.println(jsonpath.get("City"));


**Authentication API  

  Different types of autherization - Basic Auth, API Key, Bearer token

 

  //Basic authentication

  PreemptiveBasicAuthScheme authScheme=new PreemptiveBasicAuthScheme();

  authScheme.setUserName("ToolsQA");

  authScheme.setPassword("TestPassword");

  RestAssured.authentication=authscheme;


Summary

1. Define BaseURI

2. Request Object

3. Response

4. ResponseBody


Validations

-> status code

-> status line

-> response time

-> header (content-type, content-length, content-encoding etc..)

What are some common security vulnerabilities in APIs?

  • Injection attacks: These occur when untrusted data is directly included in API requests or responses, allowing attackers to execute malicious commands or inject malicious code.
  • Authentication and authorization vulnerabilities: These occur when authentication or authorization mechanisms are weak or improperly implemented, leading to unauthorized access or privilege escalation.
  • Cross-Site Scripting (XSS) attacks: These occur when an API does not properly validate or sanitize user input, allowing malicious scripts to be injected and executed in the responses displayed in web browsers.

How do you ensure the security of APIs in your tests?

Some best practices to ensure the security of APIs in your test include:

  • Input validation: Ensure all input data in API requests are properly validated and sanitized to prevent injection attacks.
  • Authentication and authorization: Properly implement and validate authentication and authorization mechanisms to ensure only authorized users can access the API endpoints and perform authorized actions.
  • Secure communications: Use secure communication protocols, such as HTTPS, to encrypt data transmitted between the client and server.

What is cross-site scripting (XSS), and how can it be prevented in API testing?

Cross-site scripting (XSS) is a type of vulnerability where malicious scripts are injected into web pages. It can be prevented by properly validating and sanitizing user input in API requests.

How do you measure the performance of APIs in your tests?

API performance is measured using key metrics like response time, latency, throughput, and error rate. Load and stress testing tools (e.g., Postman, JMeter, or k6) help evaluate API efficiency under different conditions. Monitoring uptime, scalability, and adherence to SLAs also ensures optimal API performance.

What is the purpose of API documentation in API testing?

API documentation is important in API testing to understand the API endpoints, their functionalities, and how to use them correctly. It can be generated and maintained using tools like Swagger, API Blueprint, or OpenAPI.

 How do you prioritize API test cases for regression testing?

Prioritizing API test cases for regression testing can be based on the criticality of APIs, impact on business functionalities, frequency of API usage, and feedback from stakeholders.

How do you handle API authentication in your tests?

In API tests, authentication is typically handled by including the required authentication parameters, such as tokens, API keys, or OAuth credentials, in the appropriate headers or query parameters of the API requests. 

What is the purpose of the request and response headers in API testing?

Request and response headers in API testing are used to transmit additional information about the request or response. Request headers can be used to specify a content type, authentication, caching, language preferences, etc., while response headers can provide information about the server, caching, and more.

What is the purpose of the request and response body in API testing?

The request and response body in API testing contains the payload or data that is sent in the request and response messages. The request body sends data from the client to the server, such as input parameters or data to create/update resources, while the response body contains the data returned by the API in response to a request. 

Local APIs: Local APIs allow applications within the same system to communicate with each other. Developers use them for middleware services—software that connects different applications.

What needs to be verified in API testing?

  • API testing helps to verify the correctness of data and responses. The API should return the return correct data and resposnses according to the specified requirements and expected behavior.
  • API testing should verify the functionality and behavior. The API should perform its intended functions accurately.
  • HTTP status codes of the API needs to verified.
  • Error codes if the APIs are expected to throw an error.
  • Authorization details.

 Is it possible to hack API while testing?

Yes, it is possible to hack API while testing as requests are being sent over the internet which mostly follows HTTP protocol which is a text-based protocol. Hence, it is important to perform security testing of the APIs to ensure safer systems.

Common API Vulnerabilities Exploited:

  • Broken Authentication: Weak tokens or missing authentication.
  • SQL Injection: Malicious queries to access or modify databases.
  • Cross-Site Scripting (XSS): Injecting scripts into API responses.
  • Insecure Endpoints: Exposed sensitive data due to improper access controls.
  • Rate Limiting Bypass: Exploiting APIs by sending excessive requests.

To perform API testing we need API request details, headers, payload, credentials

What is the importance of caching mechanism?

Caching mechanism is the practice of storing data temporarily to retrieve data for repeated requests. This increases the performance of the system by obtaining the data from the cached copy instead of hitting the database and getting the original data.

JSON Path Examples

==Equal to.
For example, [?(@.color == ‘blue')] matches elements whose color is blue.

Note: In the number to string comparison, 1 is not equal to ‘1’.
!=Not equal to.
For example, [?(@.color != 'red')] matches elements whose color is not red.
<Less than.
For example, [?(@.days < 30)] matches elements in which the number of days is less than 30.
<=Less than or equal to.
For example, [?(@.days <= 30)] matches elements in which the number of days is less than or equal to 30.
>Greater than.
For example, [?(@.days > 30)] matches elements in which the number of days is greater than 30.
>=Greater than.
For example, [?(@.days >= 30)] matches elements in which the number of days is greater than or equal to 30.
=~Matches a regular expression.
For example, [?(@.firstName =~ /vi.*?/i)] matches elements whose firstName starts with vi (case-insensitive).
!Negates a filter.
For example, [?(!@.isbn)] matches elements that do not have the isbn property.
&&Logical AND. Used to combine multiple filter expressions where all the conditions must be met.
For example, [?(@.isbn && @.price < 10)] matches elements that have an ISBN, and whose price is less than 10.
||Logical OR. Used to combine multiple filter expressions where any of the conditions may be met.
For example, [?(@.category == 'fiction' || @.price < 10)] matches elements whose category is fiction or whose price is less than 10.
inChecks if the value on the left exists in the set on the right.
For example, [?(@.size in ['S', ‘M'])] matches elements whose size is either ‘S’ or ‘M’.

Note: String comparison is case-sensitive.
ninChecks if the value on the left is not in the set on the right.
For example, [?(@.size nin ['S', ‘M'])] matches elements whose size is neither ‘S’ nor ‘M’.

Note: String comparison is case-sensitive.
sizeChecks if the size of the array or the string matches the specified value.
For example, [?(@.name size 12)] matches all elements whose name length is 12, including spaces.
empty trueMatches an empty array or string.
For example, [?(@.isbn empty true)] matches all elements whose isbn property has an empty value.
empty falseMatches a non-empty array or string.
For example, [?(@.isbn empty false)] matches all elements whose isbn property has a non-empty value.
{
  "event": {
    "name": "Bond Movies",
    "movies": [
      {
        "name": "Licence to Kill",
        "star": "Timothy Dalton",
        "rating": 6.6
      },
      {
        "name": "GoldenEye",
        "star": "Pierce Brosnan",
        "rating": 7.2
      },
      {
        "name": "Tomorrow Never Dies",
        "star": "Pierce Brosnan",
        "rating": 6.5
      },
      {
        "name": "Skyfall",
        "star": "Daniel Craig",
        "rating": 7.8
      }
    ]
  }
}
JSONPath                     Expression	                 Meaning
$	                   Entire object.
$.event	                   Event object.
$.event.movies[0]	   First movie.
$['event']['movies'][0]	   First movie.
$.event.movies[0,2]	   First three movies.
$.event.movies[:2]	   First two movies.
$.event.movies[-2:]	Last two movies.
$.event.movies[?(@.rating > 7)]	All movies with a rating greater than 7.
$.event.movies[?(@.star == "Pierce Brosnan")]	All movies whose star is Pierce Brosnan.
JSONPath Parameters:

The JSONPath query itself consists of a series of parameters or operators that determine how you navigate through the JSON structure. Some of the most common parameters (operators) in JSONPath include:

    $ – The root object or the current object.
        Example: $ refers to the root of the JSON document.

    . (dot) – Child operator, used to access properties of an object.
        Example: $.store refers to the store property of the root object.

    [ ] (square brackets) – Used to access elements by key (for objects) or index (for arrays).
        Example: $.store.book[0] accesses the first book in the store.book array.

    [index] – Access an array element at a specific index.
        Example: $.store.book[1] accesses the second book in the store.book array (0-based index).

    [start:end] – Slice notation for arrays, to retrieve a range of elements.
        Example: $.store.book[0:2] retrieves the first two books from the book array.

    [?()] – Filter expressions, used to select elements based on conditions.
        Example: $.store.book[?(@.price < 10)] selects books with a price less than 10.

    @ – Refers to the current element being processed.
        Example: $.store.book[?(@.category == 'fiction')] filters books in the store.book array where the category is 'fiction'.

    *** (wildcard)** – Wildcard operator, used to select all elements in an array or all properties in an object.
        Example: $.store.book[*].author selects all authors of the books in the store.book array