---
title: Write synthetic API tests
source: https://docs.newrelic.com/docs/synthetics/synthetic-monitoring/scripting-monitors/write-synthetic-api-tests
---

Scripted API monitors check your API endpoints to ensure they're functioning correctly. To create a scripted API monitor, go to **[one.newrelic.com > Synthetic monitoring > Create a monitor](https://one.newrelic.com/synthetics-nerdlets/monitor-create)**, then select the **Endpoint availability** tile.

> #### 💡 TIP
>
> To view and share other API test examples, visit the [synthetics scripts](https://support.newrelic.com/s/hubtopic/Topic__c/Default?c__categories=%5B%7B%22icon%22%3A%22standard%3Adefault%22%2C%22id%22%3A%22a6c8W000000EeseQAC%22%2C%22sObjectType%22%3A%22Category__c%22%2C%22title%22%3A%22Synthetics%22%2C%22titleFormatted%22%3A%22Synthetics%22%7D%5D) section in Support Forum or the [Synthetic Monitoring Quickstarts Library](https://newrelic.github.io/quickstarts-synthetics-library/#/).

## Use API got module [#overview]

API tests are powered by the [got module](https://github.com/sindresorhus/got), which is available through the `$http` object. The `$http` object provides a custom `request`-like experience with `got`, giving your monitors backwards compatibility for basic use cases. The `request`-like experience provided by the `$http` object will also be returned for any customers attempting to use `request` directly in Node.js 16 and newer scripted API runtimes.

Result timing details will be provided as long as you use the `$http` object. For scripted API use cases not covered by the `$http` object, you can use the `$har` object to [report custom timing details](https://docs.newrelic.com/docs/synthetics/synthetic-monitoring/scripting-monitors/custom-timing-details/).

> #### ⚠️ IMPORTANT
>
> After a maximum run time of three minutes, New Relic manually stops the script.

![syntheticApiTestScript](https://docs.newrelic.com/images/synthetic_screenshot-crop_api-test-script.webp "syntheticApiTestScript")

**[one.newrelic.com > Synthetic monitoring > Create monitor](https://one.newrelic.com/synthetics-nerdlets/monitor-create)**: The script editor suggests functions, selectors, and other elements to simplify [scripting commands (available in GitHub)](https://github.com/request/request).

## Configure request options [#request-options]

To start your script:

-   Declare a variable (such as `options`) to store your [got options object](https://github.com/sindresorhus/got/blob/main/documentation/2-options.md).
-   Define request options such as the URL endpoint and custom headers.

> #### 💡 TIP
>
> For a full list of supported options, see [got options](https://github.com/sindresorhus/got/blob/main/documentation/2-options.md) in the `got` documentation on GitHub.

Here's an example of optional metadata in the options object:

**Using optional metadata**

````js
//Declare optional metadata
var options = {
  //Specify the endpoint URL
  url: "https://api-endpoint.example.com",
  //Specify optional headers
  headers: {
    "Endpoint-Key": "uqNTC57Phe72pnnB8JuJmwAr7b09nKSKSz",
    "Additional-Header": "Additional-Header-Data",
  },
};
```

````

## Send a GET request [#get]

To make a GET request, use the [`$http.get`](https://github.com/request/request#requestget) method to submit your request. Define your [request options](#request-options), make your request using `$http.get`, then [validate](#validating) the response to ensure your endpoint is returning the correct results.

The following example demonstrates how you can:

-   Handle retries and timeouts for a GET request
-   Parse the json response body.
-   Assert on application health status.
-   Store the result in a custom attribute.

```js
/**
 * Script Name: Advanced Example - Node 16.10.0
 * Author:      New Relic
 * Version:     1.0
 */

const assert = require("assert")

// Get secure credentials
const applicationId = $secure.APP_ID
const apiKey = $secure.API_KEY

// The URL for the API endpoint to get information about a specific application
const URL = `https://api.newrelic.com/v2/applications/${applicationId}.json`

// Define headers, including the API key for authentication
const headers = {
  "X-Api-Key": apiKey,
  "Custom-Header": "CustomValue", // Example of a custom header
}

// Define got options for retries and timeouts
const options = {
  headers: headers,
  timeout: {
    request: 10000, // Set a global timeout of 10000 milliseconds for the request
  },
  retry: {
    limit: 3, // Retry a failed request up to 3 times
    statusCodes: [408, 413, 429, 500, 502, 503, 504], // Common status codes to retry on
    errorCodes: [
      "ETIMEDOUT",
      "ECONNRESET",
      "EADDRINUSE",
      "ECONNREFUSED",
      "EPIPE",
      "ENOTFOUND",
      "ENETUNREACH",
      "EAI_AGAIN",
    ],
    methods: ["GET"], // Only retry for GET requests
  },
  hooks: {
    beforeRetry: [
      (options, error, retryCount) => {
        console.error(
          `Retrying after error ${error.code}, retry #: ${retryCount}`
        )
      },
    ],
  },
}

// Make the GET request with a callback
$http.get(URL, options, function (error, response, body) {
  if (error) {
    // Handle the error case
    console.error(`Request failed: ${error.message}`)
    return
  }

  // Assert the response status code is 200
  assert.equal(response.statusCode, 200, "Expected HTTP status code 200")

  // Log the status code to the console
  console.log("Request Status Code:", response.statusCode)

  // If further processing of the response body is needed, it can be done here
  // For example, parsing JSON response (if response is in JSON format)
  const jsonData = typeof body === "string" ? JSON.parse(body) : body

  // Log the parsed JSON to the console
  console.log("Parsed JSON data:", jsonData)

  // Check the application's health status
  const healthStatus = jsonData.application.health_status
  assert.equal(healthStatus, "green", "Expected the application's health status to be 'green'")

  // If the assertion passes, the script will continue; otherwise, it will fail the monitor

  // This shows up in SyntheticCheck as `custom.healthStatus`
  $util.insights.set("healthStatus", healthStatus)
})
```

## Send a POST request [#post]

To make a POST request, use the [`$http.post`](https://github.com/request/request#requestpost) method to submit your request. Define your [request options](#request-options), make your request using `$http.post`, then [validate](#validating) the response to ensure your endpoint is returning the correct results.

**NerdGraph example**

This example queries our [NerdGraph API](https://docs.newrelic.com/docs/apis/nerdgraph/get-started/introduction-new-relic-nerdgraph):

````js
// Define your authentication credentials
const myAccountId = "YOUR_ACCOUNT_ID";
const myAPIKey = "YOUR_API_KEY";

const options = {
  // Define endpoint URI, https://api.eu.newrelic.com/graphql for EU accounts, https://api.jp.newrelic.com/graphql for JP accounts
  uri: "https://api.newrelic.com/graphql",
  headers: {
    "API-key": myAPIKey,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    query: `
          query getNrqlResults($accountId: Int!, $nrql: Nrql!) {
            actor {
              account(id: $accountId) {
                nrql(query: $nrql) {
                  results
                }
              }
            }
          }
        `,
    variables: {
      accountId: Number(myAccountId),
      nrql: "SELECT average(duration) FROM Transaction",
    },
  }),
};

// Define expected results using callback function
function callback(err, response, body) {
  // Log JSON results from endpoint to Synthetics console
  console.log(body);
  console.log("Script execution completed");
}

// Make POST request, passing in options and callback
$http.post(options, callback);
```

````

**Event API POST example**

This example POSTs a custom event containing static integers to the [Event API](https://docs.newrelic.com/docs/insights/new-relic-insights/adding-querying-data/inserting-custom-events):

````js
//Define your authentication credentials.
var myAccountID = "YOUR_ACCOUNT_ID";
var myAPIKey = "YOUR_API_KEY";
//Import the 'assert' module to validate results: https://nodejs.org/docs/latest/api/assert.html
var assert = require("assert");

var options = {
  //Define endpoint URL.
  url: "https://insights-collector.newrelic.com/v1/accounts/" + myAccountID + "/events",
  //Define body of POST request.
  body: '[{"eventType":"SyntheticsEvent","integer1":1000,"integer2":2000}]',
  //Define New Relic API key and expected data type.
  headers: {
    "Api-Key": myAPIKey,
    "Content-Type": "application/json",
  },
};

//Define expected results using callback function.
function callback(error, response, body) {
  //Log status code to Synthetics console.
  console.log(response.statusCode + " status code");
  //Verify endpoint returns 200 (OK) response code.
  assert.ok(response.statusCode == 200, "Expected 200 OK response");
  //Verify that `body` contains element named `success` with a value of `true`.
  assert.ok(
    body.success == true,
    "Expected True results in Response Body, result was " + body.success
  );
  //Log end of script.
  console.log("End reached");
}

//Make POST request, passing in options and callback.
$http.post(options, callback);
```

````

> #### ⚠️ IMPORTANT
>
> The script environment contains write protected directories. If your script requires storing files, prepend any of the following paths to the filename:
>
> -   `runtime/input-output/input/`
> -   `runtime/input-output/output/`

## Validate results [#validating]

To validate your results, import the `assert` module to define your test case. Call an `assert` method to validate your endpoint's response. If any `assert` functions fail, the entire monitor will be considered a failed check. This may trigger [alert notifications](https://docs.newrelic.com/docs/synthetics/new-relic-synthetics/using-monitors/alerting-synthetics#alerts) and affect your metrics.

> #### ⚠️ IMPORTANT
>
> Synthetic monitoring does not allow thrown exceptions. Thrown exceptions result in script failure. Use the `assert` module to validate your results, and use `console.log()` to [log results to the synthetic's console](https://docs.newrelic.com/docs/synthetics/new-relic-synthetics/scripting-monitors/writing-scripted-browsers#logging).

**Event API validation example**

This example POSTs to the Event API, then validates that the response is `{"success":true}`:

````js
//Define your authentication credentials.
var myAccountID = "YOUR_ACCOUNT_ID";
var myAPIKey = "YOUR_API_KEY";
//Import the `assert` module to validate results.
var assert = require("assert");

var options = {
  //Define endpoint URL.
  url: "https://insights-collector.newrelic.com/v1/accounts/" + myAccountID + "/events",
  //Define body of POST request.
  body: '[{"eventType":"SyntheticsEvent","integer1":1000,"integer2":2000}]',
  //Define New Relic API key and expected data type.
  headers: {
    "Api-Key": myAPIKey,
    "Content-Type": "application/json",
  },
};

$http.post(options, function (error, response, body) {
  //Log status code to Synthetics console. The status code is logged before the `assert` function,
  //because a failed assert function ends the script.
  console.log(response.statusCode + " status code");
  //Call `assert` method, expecting a `200` response code.
  //If assertion fails, log `Expected 200 OK response` as error message to Synthetics console.
  assert.ok(response.statusCode == 200, "Expected 200 OK response");
  //Call `assert` method, expecting body to return `{"success":true}`.
  //If assertion fails, log `Expected True results in Response Body,` plus results as error message to Synthetics console.
  assert.ok(
    body.success == true,
    "Expected True results in Response Body, result was " + body.success
  );
});
```

````
