---
title: Ping
description: Run a one-off HTTP, DNS, or TCP probe without creating a monitor. Built for CI checks against ephemeral deployments.
section:
  title: API Resources
  order: 7
order: 13
lastUpdated: 2026-10-24
---

The ping endpoint runs a single probe against a target you describe in the request and returns the result. No monitor is created, no check history is stored, and no alerts are sent. Use it when the target is not worth monitoring continuously — a preview deployment that lives for the length of a build, a freshly provisioned subdomain, a smoke test in a release pipeline.

Every probe uses the same regions, timeouts, and status rules as the equivalent monitor, so an ad-hoc result predicts what continuous monitoring of the same target would report.

## Request Failures Versus Target Failures

**A target that is down still returns `200`.** The outcome of the probe is in `data.ping.status`, never in the HTTP status of the API response.

A non-2xx response from this endpoint means the _request_ failed — a bad key, a missing scope, an inactive subscription, an invalid body, the rate limit, or the endpoint being unavailable to your team. It never means your target is down. Collapsing the two would make "your service is unreachable" indistinguishable from "we could not check", and only the first should fail a build.

Branch on the payload, not on the transport:

```bash
status=$(curl -s https://uptime.sergiodxa.com/api/v1/ping \
  -H "Authorization: Bearer uptime_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"type":"http","url":"https://preview-1234.example.com/healthz"}' \
  | jq -r '.data.ping.status')

case "$status" in
  up)       echo "healthy" ;;
  degraded) echo "slow but correct" ;;
  *)        echo "unhealthy: $status"; exit 1 ;;
esac
```

## Run a Ping

Run one probe and get its result back. The body's `type` selects the kind of probe, and each kind's fields are described below.

```
POST /api/v1/ping
```

**Required scope:** `ping:trigger`

### Errors

| Status | Type | Description |
| --- | --- | --- |
| 400 | `validation-error` | The request failed validation |
| 401 | `unauthorized` | The API key is missing or invalid |
| 402 | `subscription-required` | An active subscription is required |
| 403 | `forbidden` | The API key lacks the required scope |
| 429 | `rate-limited` | Too many requests |
| 503 | `endpoint-unavailable` | The endpoint is unavailable to this team |

### Request Body Schema

```json
{
	"$schema": "https://json-schema.org/draft/2020-12/schema",
	"oneOf": [
		{
			"type": "object",
			"properties": {
				"type": {
					"type": "string",
					"const": "http"
				},
				"url": {
					"type": "string",
					"format": "uri"
				},
				"method": {
					"type": "string",
					"enum": [
						"GET",
						"POST",
						"PUT",
						"PATCH",
						"DELETE",
						"HEAD"
					],
					"default": "GET"
				},
				"expectedStatus": {
					"type": "number",
					"minimum": 100,
					"maximum": 599,
					"default": 200
				},
				"timeoutSeconds": {
					"type": "number",
					"minimum": 1,
					"maximum": 60,
					"default": 10
				},
				"degradedAfterMs": {
					"type": "number",
					"minimum": 1,
					"maximum": 60000,
					"default": 5000
				},
				"region": {
					"type": "string",
					"enum": [
						"wnam",
						"enam",
						"sam",
						"weur",
						"eeur",
						"apac",
						"oc",
						"afr",
						"me"
					],
					"default": "wnam"
				},
				"headers": {
					"type": "object",
					"additionalProperties": {
						"type": "string"
					}
				},
				"body": {
					"type": "string",
					"maxLength": 10000,
					"description": "Refused when `method` is `GET` or `HEAD`"
				},
				"contentChecks": {
					"type": "array",
					"items": {
						"type": "object",
						"properties": {
							"type": {
								"type": "string",
								"enum": [
									"contains",
									"not_contains",
									"regex"
								]
							},
							"value": {
								"type": "string",
								"minLength": 1,
								"maxLength": 1000
							},
							"caseSensitive": {
								"type": "boolean",
								"default": false
							}
						},
						"required": [
							"type",
							"value"
						]
					},
					"default": []
				}
			},
			"required": [
				"type",
				"url"
			]
		},
		{
			"type": "object",
			"properties": {
				"type": {
					"type": "string",
					"const": "dns"
				},
				"domain": {
					"type": "string",
					"minLength": 1,
					"maxLength": 255
				},
				"recordType": {
					"type": "string",
					"enum": [
						"A",
						"AAAA",
						"CNAME",
						"MX",
						"TXT",
						"NS",
						"CAA",
						"TLSA",
						"DS",
						"SVCB"
					],
					"default": "A"
				},
				"expectedValue": {
					"type": "string",
					"maxLength": 1000,
					"description": "Comma-separated for multi-value records"
				}
			},
			"required": [
				"type",
				"domain"
			]
		},
		{
			"type": "object",
			"properties": {
				"type": {
					"type": "string",
					"const": "tcp"
				},
				"host": {
					"type": "string",
					"minLength": 1,
					"maxLength": 255
				},
				"port": {
					"type": "number",
					"minimum": 1,
					"maximum": 65535
				},
				"timeoutMs": {
					"type": "number",
					"minimum": 100,
					"maximum": 60000,
					"default": 5000
				}
			},
			"required": [
				"type",
				"host",
				"port"
			]
		}
	],
	"discriminator": {
		"propertyName": "type"
	}
}
```

### Response Schema

```json
{
	"$schema": "https://json-schema.org/draft/2020-12/schema",
	"type": "object",
	"properties": {
		"data": {
			"type": "object",
			"properties": {
				"ping": {
					"$ref": "#/$defs/Ping"
				}
			},
			"required": [
				"ping"
			]
		},
		"meta": {
			"type": "object",
			"properties": {
				"requestId": {
					"type": "string",
					"format": "uuid"
				},
				"timestamp": {
					"type": "string",
					"format": "date-time"
				}
			},
			"required": [
				"requestId",
				"timestamp"
			]
		}
	},
	"required": [
		"data",
		"meta"
	],
	"$defs": {
		"Ping": {
			"oneOf": [
				{
					"type": "object",
					"properties": {
						"type": {
							"type": "string",
							"const": "http"
						},
						"status": {
							"type": "string",
							"enum": [
								"up",
								"degraded",
								"down"
							]
						},
						"responseStatus": {
							"type": [
								"integer",
								"null"
							],
							"description": "Null when unreachable"
						},
						"contentChecksPassed": {
							"type": "boolean",
							"description": "True when none were supplied"
						},
						"id": {
							"type": "string",
							"pattern": "^ping_[0-7][0-9a-hjkmnp-tv-z]{25}$",
							"description": "Identifies this ping; pings are not stored"
						},
						"responseTimeMs": {
							"type": "number",
							"description": "0 when the target never answered"
						},
						"checkedAt": {
							"type": "string",
							"format": "date-time"
						}
					},
					"required": [
						"type",
						"status",
						"responseStatus",
						"contentChecksPassed",
						"id",
						"responseTimeMs",
						"checkedAt"
					]
				},
				{
					"type": "object",
					"properties": {
						"type": {
							"type": "string",
							"const": "dns"
						},
						"status": {
							"type": "string",
							"enum": [
								"ok",
								"changed",
								"error"
							],
							"description": "`changed` means the value differs from `expectedValue`"
						},
						"resolvedValue": {
							"type": [
								"string",
								"null"
							]
						},
						"errorMessage": {
							"type": [
								"string",
								"null"
							]
						},
						"id": {
							"type": "string",
							"pattern": "^ping_[0-7][0-9a-hjkmnp-tv-z]{25}$",
							"description": "Identifies this ping; pings are not stored"
						},
						"responseTimeMs": {
							"type": "number",
							"description": "0 when the target never answered"
						},
						"checkedAt": {
							"type": "string",
							"format": "date-time"
						}
					},
					"required": [
						"type",
						"status",
						"resolvedValue",
						"errorMessage",
						"id",
						"responseTimeMs",
						"checkedAt"
					]
				},
				{
					"type": "object",
					"properties": {
						"type": {
							"type": "string",
							"const": "tcp"
						},
						"status": {
							"type": "string",
							"enum": [
								"up",
								"down",
								"timeout"
							]
						},
						"errorMessage": {
							"type": [
								"string",
								"null"
							]
						},
						"id": {
							"type": "string",
							"pattern": "^ping_[0-7][0-9a-hjkmnp-tv-z]{25}$",
							"description": "Identifies this ping; pings are not stored"
						},
						"responseTimeMs": {
							"type": "number",
							"description": "0 when the target never answered"
						},
						"checkedAt": {
							"type": "string",
							"format": "date-time"
						}
					},
					"required": [
						"type",
						"status",
						"errorMessage",
						"id",
						"responseTimeMs",
						"checkedAt"
					]
				}
			],
			"discriminator": {
				"propertyName": "type"
			}
		}
	}
}
```

## Run an HTTP Ping

Probe an HTTP endpoint once and classify the response.

### Request Body

| Field             | Type    | Required | Description                                                                                                         |
| ----------------- | ------- | -------- | ------------------------------------------------------------------------------------------------------------------- |
| `type`            | string  | Yes      | Must be `http`                                                                                                      |
| `url`             | string  | Yes      | Absolute URL to probe                                                                                               |
| `method`          | string  | No       | `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, or `HEAD` (default: `GET`)                                                 |
| `expectedStatus`  | integer | No       | Response status that counts as healthy (100-599, default: 200)                                                      |
| `timeoutSeconds`  | integer | No       | Probe timeout in seconds (1-60, default: 10)                                                                        |
| `degradedAfterMs` | integer | No       | Response time above which a correct response is `degraded` (1-60000, default: 5000)                                 |
| `region`          | string  | No       | Region to probe from (default: `wnam`)                                                                              |
| `headers`         | object  | No       | Request headers, as string values keyed by header name                                                              |
| `body`            | string  | No       | Request body, up to 10,000 characters. Rejected with `400` when `method` is `GET` or `HEAD`, which cannot carry one |
| `contentChecks`   | array   | No       | Assertions run against the response body; all must pass for the status to be `up`                                   |

Each entry in `contentChecks` is an object with `type` (`contains`, `not_contains`, or `regex`), `value` (1-1000 characters), and an optional `caseSensitive` flag (default: false).

Valid regions are `wnam`, `enam`, `sam`, `weur`, `eeur`, `apac`, `oc`, `afr`, and `me`.

### cURL

```bash
curl https://uptime.sergiodxa.com/api/v1/ping \
  -H "Authorization: Bearer uptime_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "http",
    "url": "https://preview-1234.example.com/healthz",
    "method": "GET",
    "expectedStatus": 200,
    "timeoutSeconds": 10,
    "degradedAfterMs": 5000,
    "region": "wnam",
    "headers": { "X-Deploy": "preview-1234" },
    "contentChecks": [{ "type": "contains", "value": "\"status\":\"ok\"" }]
  }'
```

### Response

```json
{
	"data": {
		"ping": {
			"id": "ping_abc123",
			"type": "http",
			"status": "up",
			"responseStatus": 200,
			"responseTimeMs": 143,
			"contentChecksPassed": true,
			"checkedAt": "2026-08-01T12:00:00Z"
		}
	},
	"meta": {
		"requestId": "9f1c5f0e-4d1a-4a51-9d3f-1a2b3c4d5e6f",
		"timestamp": "2026-08-01T12:00:00Z"
	}
}
```

A target that fails returns the same `200` envelope with a different status:

```json
{
	"data": {
		"ping": {
			"id": "ping_abc124",
			"type": "http",
			"status": "down",
			"responseStatus": 503,
			"responseTimeMs": 87,
			"contentChecksPassed": false,
			"checkedAt": "2026-08-01T12:00:05Z"
		}
	},
	"meta": {
		"requestId": "0c7a6e11-2b8d-4f6c-88a1-77e3d2b91c04",
		"timestamp": "2026-08-01T12:00:05Z"
	}
}
```

## Run a DNS Ping

Resolve a DNS record once and optionally compare it against an expected value.

### Request Body

| Field           | Type   | Required | Description                                                                               |
| --------------- | ------ | -------- | ----------------------------------------------------------------------------------------- |
| `type`          | string | Yes      | Must be `dns`                                                                             |
| `domain`        | string | Yes      | Domain to resolve (1-255 characters)                                                      |
| `recordType`    | string | No       | Record type (default: `A`)                                                                |
| `expectedValue` | string | No       | Value the record must resolve to (up to 1000 characters); comma-separated for multi-value |

Valid record types are `A`, `AAAA`, `CNAME`, `MX`, `TXT`, `NS`, `CAA`, `TLSA`, `DS`, and `SVCB`.

Without `expectedValue` there is nothing to compare against, so a successful resolution is always `ok` and the `changed` status cannot occur.

### cURL

```bash
curl https://uptime.sergiodxa.com/api/v1/ping \
  -H "Authorization: Bearer uptime_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "dns",
    "domain": "preview-1234.example.com",
    "recordType": "A",
    "expectedValue": "203.0.113.10"
  }'
```

### Response

```json
{
	"data": {
		"ping": {
			"id": "ping_def456",
			"type": "dns",
			"status": "ok",
			"resolvedValue": "203.0.113.10",
			"responseTimeMs": 31,
			"errorMessage": null,
			"checkedAt": "2026-08-01T12:00:00Z"
		}
	},
	"meta": {
		"requestId": "1d4c9a72-6f0b-4e2d-9c31-58a0f4c7e2b9",
		"timestamp": "2026-08-01T12:00:00Z"
	}
}
```

A domain that does not resolve is not an error. It returns `200` with status `error` and an `errorMessage`.

## Run a TCP Ping

Open a TCP connection to a host and port once, and report whether it was accepted.

### Request Body

| Field       | Type    | Required | Description                                                   |
| ----------- | ------- | -------- | ------------------------------------------------------------- |
| `type`      | string  | Yes      | Must be `tcp`                                                 |
| `host`      | string  | Yes      | Hostname or IP address (1-255 characters)                     |
| `port`      | integer | Yes      | TCP port number (1-65535)                                     |
| `timeoutMs` | integer | No       | Connection timeout in milliseconds (100-60000, default: 5000) |

### cURL

```bash
curl https://uptime.sergiodxa.com/api/v1/ping \
  -H "Authorization: Bearer uptime_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "tcp",
    "host": "db.preview-1234.example.com",
    "port": 5432,
    "timeoutMs": 5000
  }'
```

### Response

```json
{
	"data": {
		"ping": {
			"id": "ping_ghi789",
			"type": "tcp",
			"status": "up",
			"responseTimeMs": 42,
			"errorMessage": null,
			"checkedAt": "2026-08-01T12:00:00Z"
		}
	},
	"meta": {
		"requestId": "5b2e8f30-91cd-4a77-b0a4-6c1e9d3f8210",
		"timestamp": "2026-08-01T12:00:00Z"
	}
}
```

A refused connection returns `200` with status `down`; a connection that never completes returns `200` with status `timeout`.

## Rate Limits

Ad-hoc pings are limited to **60 requests per minute per API key**. The limit is per key rather than per source address, so pipelines sharing an egress address do not consume each other's budget. Exceeding it returns a `429` `rate-limited` problem; no probe is performed and nothing is billed. See [Rate Limits](/docs/api/rate-limits) for the `RateLimit` headers this endpoint sends.

## Billing

Every accepted ping is billable and counts against the same metered ping allowance as monitor checks: the pings included in your subscription first, then whole blocks of additional pings. Requests refused before the probe runs — invalid body, missing scope, inactive subscription, rate limited — are not counted.

Ad-hoc pings belong to a team but to no monitor, so they appear in your team's monthly usage total and on no individual monitor's usage figure.

## Run a Guest Probe

Agents and CI that have no team can pay per call with [x402](https://x402.org/) instead of an API key. Marketing `/try` stays free; this route is the paid accountless lane. An unpaid request answers HTTP `402` with a `PAYMENT-REQUIRED` challenge ($0.01 USDC). After settling, retry with `PAYMENT-SIGNATURE`. No monitor is created and Polar is not billed.

```
POST /api/v1/guest/probe
```

**Authentication:** none

### Errors

| Status | Type | Description |
| --- | --- | --- |
| 400 | `validation-error` | The request failed validation |

### Request Body Schema

```json
{
	"$schema": "https://json-schema.org/draft/2020-12/schema",
	"type": "object",
	"properties": {
		"url": {
			"type": "string",
			"minLength": 1,
			"maxLength": 2048,
			"description": "The absolute URL to probe; only public http(s) hosts are allowed"
		}
	},
	"required": [
		"url"
	]
}
```

### Response Schema (200)

```json
{
	"$schema": "https://json-schema.org/draft/2020-12/schema",
	"type": "object",
	"properties": {
		"data": {
			"type": "object",
			"properties": {
				"probe": {
					"$ref": "#/$defs/GuestProbe"
				}
			},
			"required": [
				"probe"
			]
		},
		"meta": {
			"type": "object",
			"properties": {
				"requestId": {
					"type": "string",
					"format": "uuid"
				},
				"timestamp": {
					"type": "string",
					"format": "date-time"
				}
			},
			"required": [
				"requestId",
				"timestamp"
			]
		}
	},
	"required": [
		"data",
		"meta"
	],
	"$defs": {
		"GuestProbe": {
			"type": "object",
			"properties": {
				"url": {
					"type": "string",
					"description": "The normalized absolute URL that was probed"
				},
				"status": {
					"type": "string",
					"enum": [
						"up",
						"degraded",
						"down"
					]
				},
				"responseTimeMs": {
					"type": "number",
					"description": "0 when the target never answered"
				},
				"responseStatus": {
					"type": [
						"integer",
						"null"
					],
					"description": "Null when unreachable"
				},
				"location": {
					"type": [
						"string",
						"null"
					],
					"description": "Redirect target when redirects were not followed"
				},
				"checkedAt": {
					"type": "string",
					"format": "date-time"
				},
				"payment": {
					"anyOf": [
						{
							"type": "object",
							"properties": {
								"payer": {
									"type": "string"
								},
								"transaction": {
									"type": "string"
								},
								"network": {
									"type": "string"
								},
								"amount": {
									"type": "string"
								},
								"asset": {
									"type": "string"
								},
								"scheme": {
									"type": "string"
								}
							},
							"required": [
								"transaction",
								"network",
								"amount",
								"asset",
								"scheme"
							]
						},
						{
							"type": "null"
						}
					],
					"description": "Settlement receipt when payment cleared"
				}
			},
			"required": [
				"url",
				"status",
				"responseTimeMs",
				"responseStatus",
				"location",
				"checkedAt",
				"payment"
			]
		}
	}
}
```

### Request Body

| Field | Type   | Required | Description                                                         |
| ----- | ------ | -------- | ------------------------------------------------------------------- |
| `url` | string | Yes      | Absolute URL to probe; only public `http`/`https` hosts are allowed |

### cURL

```bash
# Unpaid → 402 with PAYMENT-REQUIRED
curl -i https://uptime.sergiodxa.com/api/v1/guest/probe \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com"}'

# After settling, retry with PAYMENT-SIGNATURE
curl https://uptime.sergiodxa.com/api/v1/guest/probe \
  -H "Content-Type: application/json" \
  -H "PAYMENT-SIGNATURE: …" \
  -d '{"url":"https://example.com"}'
```
