> ## Documentation Index
> Fetch the complete documentation index at: https://developers.entri.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Monitor Endpoints

> REST endpoints for Entri Monitor: /monitor/domains, /monitor/domains/batch, /monitor/status.

## Entri Monitor API

## General API Guidelines

### Base URL

```
https://api.goentri.com
```

### Authentication

All requests require the following headers:

* **`applicationId`**: Your unique application ID.

* **`Authorization`**: A bearer token generated using your client secret.

**Example Headers**:

```http theme={"system"}
applicationId: your-app-id
Authorization: Bearer your-auth-token
```

<Note>
  Monitor endpoints are protected by a **custom Lambda authorizer** that validates the `applicationId` + `Authorization` pair on every request. Authorizer results are **not cached**. Each request is re-authorized, so always send a valid, unexpired token.
</Note>

### DNS record format

Wherever an endpoint accepts a `dnsRecords` array, each record has the following shape:

| Field   | Type    | Description                                                                 |
| ------- | ------- | --------------------------------------------------------------------------- |
| `type`  | string  | One of `A`, `AAAA`, `CNAME`, `MX`, `TXT`, `NS`, `SOA`, `SRV`, `PTR`, `CAA`. |
| `host`  | string  | The record host.                                                            |
| `value` | string  | The record value.                                                           |
| `ttl`   | integer | Time to live, in seconds. Must be greater than 0.                           |

The `/monitor/domains/:domain_name/records` endpoints validate these fields strictly: an unsupported record `type`, an empty `host` or `value`, a `ttl` of 0 or less, or an empty `dnsRecords` array is rejected with a `400` response.

## Quickstart

### Step 1:  Add domains for monitoring

You'll first need to tell Entri Monitor which domain you'd like to monitor. Send a `POST` request to `/monitor/domains` with the name of the domain, as well as a list of the records you want to monitor, including their `type`, `host`, `value`, and `ttl` properties.

Example request body:

```json theme={"system"}
{
  "domain": "example.com",
  "dnsRecords": [
    {
      "type": "A",
      "host": "@",
      "value": "93.184.216.34",
      "ttl": 3600
    }
  ]
}
```

You'll receive a `201` response like this if you're successful:

```json theme={"system"}
{
  "message": "Domain successfully added"
}
```

### Step 2: Specify a webhook URL

Log into the Entri Dashboard and navigate to the App Settings page. Enter the URL of the webhook that you'll use to receive notifications about the DNS changes you specified.

### Step 3: Set up your service to receive the webhook requests at the URL you specified

Your webhook URL will be sent requests if the DNS records you specified are modified or deleted. Example request:

```json theme={"system"}
{
 "id": "e98d267b-84b8-4229-a94a-1933ed7f91ea",
 "subdomain": "www",
 "domain": "example.com",
 "user_id": "user123",
 "type": "domain.record_missing" / "domain.record_restored",
 "data": {
  "records_propagated": [
   {
    "host": "www",
    "ttl": 300,
    "type": "CNAME",
    "value": "mydestinationdomain.com"
   }
  ],
  "records_non_propagated": [
   {
    "host": "@",
    "ttl": 300,
    "type": "TXT",
    "value": "domain_verification123"
   }
  ]
 },
 "connect_link": "https://customurl.goentri.dev/share/27bc7873e6ad452780686b8c0436eb75"
}
```

## Retrieve DNS records

```
GET https://api.goentri.com/monitor/domains/:domain_name/records
Header "Authorization: [JWT authorization]"
Header "applicationId: [yourApplicationID]"
```

### Query parameters

* `subdomain` (string, optional): Target the records monitored for a specific subdomain of `domain_name`. Omit it to target the records monitored on the apex domain.

### Successful response (200 status)

Returns the monitored records as a JSON array:

```JSON JSON theme={"system"}
[
  {
    "type": "A",
    "host": "example.com",
    "value": "93.184.216.34",
    "ttl": 3600
  }
]
```

Returns a `404` response if the domain is not monitored or your application is not authorized to access it.

## Create DNS records

Adds the given records to the set already being monitored for the domain. Existing monitored records are kept.

```
POST https://api.goentri.com/monitor/domains/:domain_name/records
Header "Authorization: [JWT authorization]"
Header "applicationId: [yourApplicationID]"
```

### Query parameters

* `subdomain` (string, optional): Target a specific subdomain of `domain_name`. Omit it to target the apex domain.

### Request body

```JSON JSON theme={"system"}
{
  "dnsRecords": [
    {
      "type": "A",
      "host": "example.com",
      "value": "93.184.216.34",
      "ttl": 3600
    }
  ]
}
```

### Successful response (200 status)

```JSON JSON theme={"system"}
{
  "message": "DNS Records successfully updated"
}
```

## Update DNS records

Replaces the full set of monitored records for the domain (or subdomain) with the records in the request. Any previously monitored record not included in the request stops being monitored.

```
PUT https://api.goentri.com/monitor/domains/:domain_name/records
Header "Authorization: [JWT authorization]"
Header "applicationId: [yourApplicationID]"
```

### Query parameters

* `subdomain` (string, optional): Target a specific subdomain of `domain_name`. Omit it to target the apex domain.

### Request body

```JSON JSON theme={"system"}
{
  "dnsRecords": [
    {
      "type": "TXT",
      "host": "example.com",
      "value": "v=spf1 include:_spf.example.com ~all",
      "ttl": 3600
    }
  ]
}
```

### Successful response (201 status)

```JSON JSON theme={"system"}
{
  "message": "DNS Records successfully updated"
}
```

## Delete DNS records

Removes the given records from the monitored set. Monitored records that don't match a record in the request are kept.

```
DELETE https://api.goentri.com/monitor/domains/:domain_name/records
Header "Authorization: [JWT authorization]"
Header "applicationId: [yourApplicationID]"
```

### Query parameters

* `subdomain` (string, optional): Target a specific subdomain of `domain_name`. Omit it to target the apex domain.

### Request body

```JSON JSON theme={"system"}
{
  "dnsRecords": [
    {
      "type": "CNAME",
      "host": "www.example.com",
      "value": "example.com",
      "ttl": 3600
    }
  ]
}
```

### Successful response (200 status)

```JSON JSON theme={"system"}
{
  "message": "DNS record(s) successfully deleted"
}
```

## The domain object

The endpoints that return monitored domains use the following shape:

| Field                           | Description                                                                                      |
| ------------------------------- | ------------------------------------------------------------------------------------------------ |
| `id`                            | Unique identifier of the monitored domain.                                                       |
| `domain`                        | The apex domain name.                                                                            |
| `subdomain`                     | The monitored subdomain, or `null` for the apex domain.                                          |
| `date_added`                    | Date the domain was added to Monitor.                                                            |
| `dns_records`                   | The records being monitored.                                                                     |
| `records_present`               | Monitored records that were found on the domain during the latest check.                         |
| `records_missing`               | Monitored records that were not found on the domain during the latest check.                     |
| `missing_records_last_detected` | When missing records were last detected, or `null`.                                              |
| `last_checked_at`               | When the domain's records were last checked by Monitor, or `null` if it hasn't been checked yet. |
| `is_active`                     | Whether monitoring is currently active for the domain.                                           |
| `user_id`                       | The `userId` you provided when adding the domain, or `null`.                                     |
| `job_id`                        | The `jobId` you provided when adding the domain, or `null`.                                      |
| `source`                        | How the domain was enrolled. Domains added through these endpoints have the source `api`.        |
| `application_id`                | The application the domain belongs to.                                                           |

## List domains

```
GET https://api.goentri.com/monitor/domains
Header "Authorization: [JWT authorization]"
Header "applicationId: [yourApplicationID]"
```

### Query parameters

* `domain` (string): Return a single monitored domain by name instead of a paginated list.
* `offset` (integer): Pagination offset. Defaults to `0`.
* `limit` (integer): Number of domains per page. Defaults to `10`.
* `from_date` (date): Filter start date. Must be sent together with `to_date`.
* `to_date` (date): Filter end date. Must be sent together with `from_date`.

### Successful response (200 status)

```JSON JSON theme={"system"}
{
  "domains": [
    {
      "id": "0b0e7d0c-6f36-4f1b-9a52-7f6f1c2ab001",
      "domain": "example.com",
      "subdomain": null,
      "date_added": "2026-08-01",
      "dns_records": [
        {
          "type": "A",
          "host": "example.com",
          "value": "93.184.216.34",
          "ttl": 3600
        }
      ],
      "records_present": [
        {
          "type": "A",
          "host": "example.com",
          "value": "93.184.216.34",
          "ttl": 3600
        }
      ],
      "records_missing": null,
      "missing_records_last_detected": null,
      "last_checked_at": "2026-08-20T09:00:00",
      "is_active": true,
      "user_id": "user123",
      "job_id": null,
      "source": "api",
      "application_id": "your-app-id"
    }
  ],
  "page": 0,
  "totalItems": 1
}
```

`page` echoes the `offset` you sent and `totalItems` is the number of domains returned in this response. See [The domain object](#the-domain-object) for the fields of each entry.

## Retrieve domain details

```
GET https://api.goentri.com/monitor/domains/:domain_name
Header "Authorization: [JWT authorization]"
Header "applicationId: [yourApplicationID]"
```

### Query parameters

* `subdomain` (string, optional): Target the monitored domain for a specific subdomain of `domain_name`. Omit it to target the monitored domain on the apex domain (the entry with no subdomain). It does not return "all subdomains" of `domain_name`. To look up a specific subdomain, pass its exact value (for example, `shop`).

### Successful response (200 status)

Returns a single [domain object](#the-domain-object):

```JSON JSON theme={"system"}
{
  "id": "0b0e7d0c-6f36-4f1b-9a52-7f6f1c2ab001",
  "domain": "example.com",
  "subdomain": null,
  "date_added": "2026-08-01",
  "dns_records": [
    {
      "type": "A",
      "host": "example.com",
      "value": "93.184.216.34",
      "ttl": 3600
    }
  ],
  "records_present": [
    {
      "type": "A",
      "host": "example.com",
      "value": "93.184.216.34",
      "ttl": 3600
    }
  ],
  "records_missing": null,
  "missing_records_last_detected": null,
  "last_checked_at": "2026-08-20T09:00:00",
  "is_active": true,
  "user_id": "user123",
  "job_id": null,
  "source": "api",
  "application_id": "your-app-id"
}
```

Returns a `404` response if the domain is not monitored or your application is not authorized to access it.

## Add a domain

```
POST https://api.goentri.com/monitor/domains
Header "Authorization: [JWT authorization]"
Header "applicationId: [yourApplicationID]"
```

### Request body

```JSON JSON theme={"system"}
{
  "domain": "example.com",
  "dnsRecords": [
    {
      "type": "A",
      "host": "example.com",
      "value": "93.184.216.34",
      "ttl": 3600
    }
  ],
  "userId": "UUID"
}
```

### Request parameters

| Parameter    | Type   | Required? | Description                                                                                         |
| ------------ | ------ | --------- | --------------------------------------------------------------------------------------------------- |
| `domain`     | string | Yes       | The apex domain to monitor.                                                                         |
| `dnsRecords` | array  | Yes       | The records to monitor. See [DNS record format](#dns-record-format).                                |
| `subdomain`  | string | No        | Monitor the records for a specific subdomain of `domain` (for example, `shop` under `example.com`). |
| `userId`     | string | No        | Your identifier for the end user. Echoed back as `user_id` in webhook payloads and domain objects.  |
| `jobId`      | string | No        | Your identifier for the setup job that created this domain. Echoed back as `job_id`.                |
| `userEmail`  | string | No        | The email address of the end user.                                                                  |

If the domain is already being monitored, this request updates it with the DNS records provided.

### Successful response (201 status)

```JSON JSON theme={"system"}
{
  "message": "Domain successfully added"
}
```

## Update a domain

Replaces the monitored records of an existing domain.

```
PUT https://api.goentri.com/monitor/domains
Header "Authorization: [JWT authorization]"
Header "applicationId: [yourApplicationID]"
```

### Request body

```JSON JSON theme={"system"}
{
  "domain": "example.com",
  "dnsRecords": [
    {
      "type": "A",
      "host": "example.com",
      "value": "93.184.216.34",
      "ttl": 3600
    }
  ],
  "userId": "UUID"
}
```

### Request parameters

| Parameter    | Type   | Required? | Description                                        |
| ------------ | ------ | --------- | -------------------------------------------------- |
| `domain`     | string | Yes       | The apex domain to update.                         |
| `dnsRecords` | array  | Yes       | The new set of records to monitor.                 |
| `subdomain`  | string | No        | Target a specific monitored subdomain of `domain`. |
| `userId`     | string | No        | Your identifier for the end user.                  |

Returns a `404` response if the domain is not being monitored.

### Successful response (200 status)

```JSON JSON theme={"system"}
{
  "message": "Domain successfully updated."
}
```

## Delete a domain

```
DELETE https://api.goentri.com/monitor/domains
Header "Authorization: [JWT authorization]"
Header "applicationId: [yourApplicationID]"
```

### Request body

```JSON JSON theme={"system"}
{
  "domain": "example.com",
  "subdomain": "shop",
  "deleteOnlyIfEmpty": true
}
```

### Request parameters

| Parameter           | Type    | Required? | Default | Description                                                                                                                                                                                                                                                      |
| ------------------- | ------- | --------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `domain`            | string  | Yes       | N/A     | The apex domain to delete from Monitor.                                                                                                                                                                                                                          |
| `subdomain`         | string  | No        | N/A     | When provided, deletes monitoring only for the given subdomain under `domain` (for example, `shop` under `example.com`). The apex is kept intact.                                                                                                                |
| `deleteOnlyIfEmpty` | boolean | No        | false   | When `true`, the domain (or subdomain) is only deleted if it has **no remaining monitored DNS records**. If records still exist, or the domain is already deleted, the request is rejected with a `400` response. Useful when reconciling from multiple sources. |

All parameters must be sent in the request body. Query parameters are not supported on this endpoint.

### Successful response (200 status)

```JSON JSON theme={"system"}
{
  "message": "Domain successfully deleted"
}
```

Returns a `400` response with an explanatory message if the domain is not being monitored, is already deleted, or `deleteOnlyIfEmpty` is `true` and monitored records still exist.

## Batch create domains

<Note>
  Each batch request is limited to a maximum of **100 domains**. Submit multiple batches if you need to register more than 100 at once.
</Note>

```
POST https://api.goentri.com/monitor/domains/batch
Header "Authorization: [JWT authorization]"
Header "applicationId: [yourApplicationID]"
```

### Request body

```JSON JSON theme={"system"}
{
  "domains": [
    {
      "domain": "example.com",
      "dnsRecords": [
        {
          "type": "A",
          "host": "example.com",
          "value": "93.184.216.34",
          "ttl": 3600
        }
      ]
    },
    {
      "domain": "example2.com",
      "dnsRecords": [
        {
          "type": "A",
          "host": "example.com",
          "value": "93.184.216.34",
          "ttl": 3600
        }
      ]
    }
  ]
}
```

Each entry in `domains` accepts the same fields as [Add a domain](#add-a-domain).

### Successful response (201 status)

The batch is processed asynchronously. Use the returned `request_id` with the [Batch status](#batch-status) endpoint to track its progress.

```JSON JSON theme={"system"}
{
  "request_id": "e98d267b-84b8-4229-a94a-1933ed7f91ea",
  "status": "IN_PROGRESS"
}
```

## Batch delete domains

Deletes multiple monitored domains in a single request. The batch is processed asynchronously: the endpoint validates and queues the request, then returns a `request_id` that you can use to track progress through the [Batch status](#batch-status) endpoint.

<Note>
  Each batch request is limited to a maximum of **1000 domains**. Submit multiple batches if you need to delete more than 1000 at once.
</Note>

```
DELETE https://api.goentri.com/monitor/domains/batch
Header "Authorization: [JWT authorization]"
Header "applicationId: [yourApplicationID]"
```

### Request body

```JSON JSON theme={"system"}
{
  "domains": [
    {
      "domain": "example.com"
    },
    {
      "domain": "example.com",
      "subdomain": "shop"
    },
    {
      "domain": "example2.com",
      "deleteOnlyIfEmpty": true
    }
  ]
}
```

### Request parameters

Each item in the `domains` array accepts the same options as [Delete a domain](#delete-a-domain):

| Parameter           | Type    | Required? | Default | Description                                                                                                                                                |
| ------------------- | ------- | --------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `domain`            | string  | Yes       | N/A     | The apex domain to delete from Monitor.                                                                                                                    |
| `subdomain`         | string  | No        | N/A     | When provided, deletes monitoring only for the given subdomain under `domain`. Omit it (or send `null`) to target the entry monitored for the root domain. |
| `deleteOnlyIfEmpty` | boolean | No        | false   | Same behavior as the `deleteOnlyIfEmpty` option on [Delete a domain](#delete-a-domain), applied per item.                                                  |

Each item is matched against your monitored domains by its `domain` and `subdomain` pair. Items that cannot be matched, or that fail validation, fail individually without affecting the rest of the batch; they are reported through the [Batch status](#batch-status) endpoint.

### Successful response (201 status)

```JSON JSON theme={"system"}
{
  "request_id": "9c128fe4-63cd-4ec4-9ae8-8a9d06c0e6de",
  "status": "IN_PROGRESS"
}
```

The deletions happen in the background. Poll the [Batch status](#batch-status) endpoint with the returned `request_id` to check the result.

### Error responses

| HTTP | Example Body                                             | Description                              |
| ---: | -------------------------------------------------------- | ---------------------------------------- |
|  400 | `{ "message": "Missing domains in the request body." }`  | The `domains` array is missing or empty. |
|  400 | `{ "message": "The maximum number of domains is 1000" }` | More than 1000 domains were submitted.   |
|  500 | `{ "message": "Internal Server Error" }`                 | Unexpected server error.                 |

## Batch status

Returns the status of a batch create or batch delete request, using the `request_id` returned when the batch was submitted.

<Note>
  Batch status records are retained for **7 days** (TTL) after the batch is submitted. After that window, status lookups for old batches will return a not-found response.
</Note>

```
GET https://api.goentri.com/monitor/domains/batch/status/:request_id
Header "Authorization: [JWT authorization]"
Header "applicationId: [yourApplicationID]"
```

### Successful response (200 status)

```JSON JSON theme={"system"}
{
  "batchId": "0c9f9d7a-2b1e-4c3d-8e5f-6a7b8c9d0e1f",
  "applicationId": "your-app-id",
  "status": "SUCCESS",
  "successfulDomains": 10
}
```

When one or more items fail, the response also includes a `failedDomains` object listing them:

```JSON JSON theme={"system"}
{
  "batchId": "0c9f9d7a-2b1e-4c3d-8e5f-6a7b8c9d0e1f",
  "applicationId": "your-app-id",
  "status": "FAILED",
  "successfulDomains": 9,
  "failedDomains": {
    "count": 1,
    "domains": [
      {
        "domain": "example.com",
        "subdomain": "shop"
      }
    ]
  }
}
```

### Response fields

| Field               | Type    | Description                                                                                                                |
| ------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------- |
| `batchId`           | string  | The identifier assigned to the batch.                                                                                      |
| `applicationId`     | string  | Your application ID.                                                                                                       |
| `status`            | string  | `IN_PROGRESS` while the batch is being processed, `SUCCESS` when every item completed, or `FAILED` if any item failed.     |
| `successfulDomains` | integer | The number of items that completed successfully.                                                                           |
| `failedDomains`     | object  | Only present when at least one item failed. Contains `count` and `domains`, the list of items that could not be processed. |

Returns a `404` response if there is no status for the given request ID (including expired records), and a `403` response if the request belongs to a different application.

## Monitor service status

Returns the current health of the Entri Monitor service itself, based on its most recent internal health check.

```
GET https://api.goentri.com/monitor/status
Header "Authorization: [JWT authorization]"
Header "applicationId: [yourApplicationID]"
```

### Successful response (200 status)

```JSON JSON theme={"system"}
{
  "status": "healthy",
  "executedAt": "2026-08-18T09:00:00"
}
```

`status` is either `"healthy"` or `"unhealthy"`, and `executedAt` is the timestamp of the last health check run.

## Webhooks

To receive webhook notifications about the target domains, log into the Entri Dashboard and navigate to the App Settings page. Enter the URL of the webhook that you'll use to receive notifications about the DNS changes you specified.

Your webhook URL will be sent requests if the DNS records you specified are modified or deleted.

### Top-Level fields

* **`id`**: A unique identifier for the webhook event (e.g. `"e98d267b-84b8-4229-a94a-1933ed7f91ea"`).
* **`user_id`**: The ID of the user who initiated the domain-related action (e.g. `"your-provided-user-id"`).
* **`domain`**: The domain involved in the event (e.g. `"example.com"`).
* **`subdomain`**: The subdomain associated with the event, if any (e.g. `"shop"`).
* **`type`**: Defines the type of event. Possible values:
  * `"domain.record_missing"`: Used whenever there is a record missing from the records that are being monitored.
  * `"domain.record_restored"`: Confirms that ALL records have been restored.
* **`data.records_propagated`**: Contains all the records that are being monitored and **were found correctly** configured on the domain.
* **`data.records_non_propagated`**: Contains all the records that are being monitored and **were found as missing** on the domain.
* **`connect_link`**: Entri Connect's sharing link with the configuration required to re-establish the missing records on the domain.

Example request:

```json theme={"system"}
{
 "id": "e98d267b-84b8-4229-a94a-1933ed7f91ea",
 "subdomain": "www",
 "domain": "example.com",
 "user_id": "user123",
 "type": "domain.record_missing" / "domain.record_restored",
 "data": {
  "records_propagated": [
   {
    "host": "www",
    "ttl": 300,
    "type": "CNAME",
    "value": "mydestinationdomain.com"
   }
  ],
  "records_non_propagated": [
   {
    "host": "@",
    "ttl": 300,
    "type": "TXT",
    "value": "domain_verification123"
   }
  ]
 },
 "connect_link": "https://customurl.goentri.dev/share/27bc7873e6ad452780686b8c0436eb75"
}
```
