Docs
Phone call alert API for AI agents.
AgentPing is a phone call alert API for AI agents. Use it when the user may not see chat in time and the action is urgent, time-sensitive, or costly to miss.
Best for urgent reminders, missed-chat escalation, approvals, incidents, threshold alerts, and other agent-to-human escalation.
This page stays copy-paste friendly on purpose: stable headings, explicit JSON examples, and minimal decoration so agents, scripts, and humans can all use it reliably.
Base URL: https://api.agentping.me
Quickstart
Get your first alert in 5 steps: sign up, verify your phone number, generate an API key, send an alert, and check your phone.
{
"base_url": "https://api.agentping.me",
"auth_header": "X-API-Key",
"create_alert": "POST /v1/alerts",
"get_alert": "GET /v1/alerts/{id}",
"acknowledge_alert": "POST /v1/alerts/{id}/acknowledge",
"canonical_severities": ["normal", "critical"],
"default_severity": "normal",
"critical_bypasses_quiet_hours": true
}# 1. Sign up at agentping.me/signup
# 2. Verify your phone number in the dashboard
# 3. Generate an API key at agentping.me/api-keys
# 4. Send your first alert:
curl -X POST https://api.agentping.me/v1/alerts \
-H "Content-Type: application/json" \
-H "X-API-Key: ap_sk_your_key_here" \
-d '{"title": "Hello from my agent!", "severity": "normal"}'
# 5. Check your phone — you should receive a call within seconds.Integration Guides
If you are wiring AgentPing into an existing agent framework, use a guide instead of stitching together API examples by hand.
OpenClaw Setup Guide
Full setup for the ClawHub skill: create an API key, set AGENTPING_API_KEY in OpenClaw, follow the recommended schedule-first escalation pattern, and verify the integration with a real voice alert.
Claude Code Setup Guide
Install the AgentPing skill in Claude Code so your coding agent can call you when a task finishes or when it gets stuck and needs your input.
Agent Integration Rules
If you are wiring AgentPing into an LLM agent, automation, or scraper, these are the recommended rules:
1. Try chat first. Use AgentPing when the user truly needs to notice.
2. Use severity="normal" by default.
3. Use severity="critical" only when the alert must bypass quiet hours.
4. Always send title. Send message when spoken context will help.
5. Pass alert_type to get a sensible default delay for approvals, failures, reminders, or thresholds.
6. If the user responds in chat before delivery starts, call POST /v1/alerts/{id}/acknowledge with {"ack_source":"chat"}.
7. Never target arbitrary third-party numbers. phone_number must already be verified on the same account.OpenAI Tool Format
AgentPing works well with the OpenAI Responses API. Define one function tool, let the model decide when to escalate, then POST the tool arguments to AgentPing.
Tool definition
This uses OpenAI's current function-tool shape.
{
"type": "function",
"name": "agentping_alert",
"description": "Escalate an alert to the user's verified phone via AgentPing. Use this only after trying chat or when the user truly needs immediate attention.",
"parameters": {
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Short summary of what needs attention. Max 500 chars."
},
"severity": {
"type": "string",
"enum": ["normal", "critical"],
"description": "normal respects quiet hours. critical bypasses quiet hours."
},
"message": {
"type": "string",
"description": "Longer context that may be read aloud in the call. Max 2000 chars."
},
"alert_type": {
"type": "string",
"enum": ["approval", "task_failure", "threshold", "reminder", "other"],
"description": "Category that sets the default delay before escalation."
},
"delay_seconds": {
"type": "integer",
"description": "Optional explicit delay before first delivery. 0 to 3600."
},
"phone_number": {
"type": "string",
"description": "Optional verified E.164 number on the same account."
},
"metadata": {
"type": "object",
"description": "Optional JSON object stored with the alert."
}
},
"required": ["title", "severity"],
"additionalProperties": false
}
}OpenAI example with SDK
The SDK provides tool_definition() and handle_tool_call() so you don't need to manage the tool schema or HTTP calls yourself.
from openai import OpenAI
from agentping import AgentPingClient, tool_definition, handle_tool_call
import json
openai = OpenAI()
agentping = AgentPingClient(api_key="ap_sk_...")
response = openai.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "You are a helpful assistant. "
"Use agentping_alert to escalate when the user hasn't responded."},
{"role": "user", "content": "Monitor my deploy and alert me if it fails."},
],
tools=[tool_definition()],
)
for tool_call in response.choices[0].message.tool_calls or []:
if tool_call.function.name == "agentping_alert":
args = json.loads(tool_call.function.arguments)
result = handle_tool_call(agentping, args)
print(f"Alert sent: {result['id']}")OpenAI Responses API (raw HTTP)
If you prefer not to use the SDK, wire the tool manually. When the model emits a function_call, POST the parsed arguments to AgentPing, then return the result as function_call_output.
from openai import OpenAI
import httpx
import json
client = OpenAI()
AGENTPING_KEY = "ap_sk_..."
tools = [{
"type": "function",
"name": "agentping_alert",
"description": "Escalate an alert to the user's verified phone via AgentPing.",
"parameters": {
"type": "object",
"properties": {
"title": {"type": "string"},
"severity": {"type": "string", "enum": ["normal", "critical"]},
"message": {"type": "string"},
"alert_type": {
"type": "string",
"enum": ["approval", "task_failure", "threshold", "reminder", "other"]
}
},
"required": ["title", "severity"],
"additionalProperties": false
}
}]
input_messages = [{
"role": "user",
"content": "The deploy is ready but needs human approval. If the user does not reply in chat, escalate."
}]
response = client.responses.create(model="gpt-5.4", input=input_messages, tools=tools)
tool_outputs = []
for item in response.output:
if item.type == "function_call" and item.name == "agentping_alert":
args = json.loads(item.arguments)
result = httpx.post(
"https://api.agentping.me/v1/alerts",
headers={
"Content-Type": "application/json",
"X-API-Key": AGENTPING_KEY,
},
json=args,
timeout=10.0,
)
result.raise_for_status()
tool_outputs.append({
"type": "function_call_output",
"call_id": item.call_id,
"output": result.text,
})
if tool_outputs:
input_messages.extend(tool_outputs)
final_response = client.responses.create(
model="gpt-5.4",
input=input_messages,
tools=tools,
)
print(final_response.output_text)Direct HTTP example
The tool implementation is just an authenticated HTTP POST.
curl -X POST https://api.agentping.me/v1/alerts \
-H "Content-Type: application/json" \
-H "X-API-Key: ap_sk_..." \
-d '{
"title": "Deploy approval needed",
"severity": "normal",
"message": "Release v2.4.1 is waiting for approval.",
"alert_type": "approval",
"delay_seconds": 300
}'SDKs
Official SDKs for Python and TypeScript. Both include a typed client, error classes, and an OpenAI-compatible tool definition you can plug into any agent framework.
Install
# Python pip install agentping-sdk # TypeScript / JavaScript npm install agentping-sdk
Python quick start
from agentping import AgentPingClient
client = AgentPingClient(api_key="ap_sk_...")
alert = client.send_alert(
title="Deploy approval needed",
severity="normal",
message="v2.4.1 ready for production. 3 migrations pending.",
alert_type="approval",
)
print(alert["id"]) # "550e8400-..."
print(alert["status"]) # "escalating_call"
# Check status later
status = client.get_alert(alert["id"])
# Acknowledge programmatically (stops escalation)
client.acknowledge(alert["id"])TypeScript quick start
import { AgentPingClient } from "agentping-sdk";
const client = new AgentPingClient({ apiKey: "ap_sk_..." });
const alert = await client.sendAlert({
title: "Deploy approval needed",
severity: "normal",
message: "v2.4.1 ready for production. 3 migrations pending.",
alert_type: "approval",
});
console.log(alert.id); // "550e8400-..."
console.log(alert.status); // "escalating_call"
// Check status later
const status = await client.getAlert(alert.id);
// Acknowledge programmatically (stops escalation)
await client.acknowledge(alert.id);Built-in tool helpers
Both SDKs include toolDefinition() and handleToolCall() for plugging AgentPing into any agent framework with one line.
# Python from agentping import AgentPingClient, tool_definition, handle_tool_call client = AgentPingClient(api_key="ap_sk_...") tools = [tool_definition()] # OpenAI-compatible function tool # When the agent calls the tool: result = handle_tool_call(client, tool_call_args)
// TypeScript
import { AgentPingClient, toolDefinition, handleToolCall } from "agentping-sdk";
const client = new AgentPingClient({ apiKey: "ap_sk_..." });
const tools = [toolDefinition()]; // OpenAI-compatible function tool
// When the agent calls the tool:
const result = await handleToolCall(client, toolCallArgs);Authentication
All API requests require an API key in the X-API-Key header. Generate keys from your API Keys dashboard.
curl https://api.agentping.me/v1/alerts \ -H "X-API-Key: ap_sk_..."
Keys start with ap_sk_ and are shown only once at creation time. Store them securely.
Create Alert
Send an alert to your verified phone number. AgentPing delivers it via voice call, with retries based on the severity level.
/v1/alertsRequest body
| Field | Type | Required | Description |
|---|---|---|---|
| title | string | Yes | Short title for the alert (1–500 chars) |
| severity | string | Yes | Canonical values: normal critical. Deprecated aliases still accepted: low urgent persistent_critical. |
| message | string | No | Longer description or context (max 2000 chars) |
| alert_type | string | No | approval task_failure threshold reminder other. Defaults to other. Sets default escalation timing. |
| delay_seconds | integer | No | Seconds to wait before delivery (0–3600). Overrides alert_type default. Use this for the "chat first, then escalate" pattern. |
| phone_number | string | No | Verified E.164 number (e.g. +14155550123). Defaults to your primary verified phone. |
| expires_in_minutes | integer | No | Auto-expire after N minutes (1–1440). Defaults by severity: normal=60, critical=30. |
| metadata | object | No | Arbitrary key-value data stored with the alert |
Example request
curl -X POST https://api.agentping.me/v1/alerts \
-H "Content-Type: application/json" \
-H "X-API-Key: ap_sk_abc123..." \
-d '{
"title": "Deploy approval needed",
"message": "v2.4.1 ready for production. 3 migrations pending.",
"severity": "normal",
"alert_type": "approval",
"delay_seconds": 300,
"expires_in_minutes": 30
}'Response (201 Created)
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "waiting_for_primary_ack",
"severity": "normal",
"alert_type": "approval",
"title": "Deploy approval needed",
"created_at": "2026-03-14T12:00:00Z",
"expires_at": "2026-03-14T12:30:00Z"
}Get Alert Status
Retrieve the current status, delivery history, and acknowledgement details of an alert.
/v1/alerts/{id}Response (200 OK)
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "acknowledged",
"severity": "normal",
"alert_type": "approval",
"title": "Deploy approval needed",
"message": "v2.4.1 ready for production. 3 migrations pending.",
"acknowledged_at": "2026-03-14T12:03:22Z",
"acknowledged_via": "dtmf",
"escalation_step": 0,
"delay_seconds": 300,
"expires_at": "2026-03-14T12:30:00Z",
"created_at": "2026-03-14T12:00:00Z",
"metadata": { "action": "deploy", "version": "v2.4.1" },
"deliveries": [
{
"id": "d1a2b3c4...",
"alert_id": "550e8400...",
"channel": "voice",
"status": "delivered",
"to_number": "+14155550123",
"provider_sid": "CA...",
"error_message": null,
"created_at": "2026-03-14T12:00:01Z"
}
]
}Response fields
| Field | Type | Description |
|---|---|---|
| id | string | UUID of the alert |
| status | string | Current state (see lifecycle) |
| severity | string | Alert severity level |
| alert_type | string | Alert category |
| title | string | Alert title |
| message | string | null | Alert message body |
| acknowledged_at | string | null | ISO 8601 timestamp of acknowledgement |
| acknowledged_via | string | null | dtmf sms_link api chat sms_reply manual |
| escalation_step | integer | Current step in the escalation plan (0-based) |
| delay_seconds | integer | Configured delay before first delivery |
| expires_at | string | null | ISO 8601 expiry timestamp |
| created_at | string | ISO 8601 creation timestamp |
| metadata | object | null | Custom data attached to the alert |
| deliveries | array | null | List of delivery attempts with channel, status, and timestamps |
Acknowledge Alert
Programmatically acknowledge an alert to stop escalation. Users can also acknowledge via phone keypad (press 0 to ack, 1 to snooze).
/v1/alerts/{id}/acknowledgeRequest body (optional)
{
"ack_source": "api"
}| Field | Type | Default | Description |
|---|---|---|---|
| ack_source | string | "api" | dtmf sms_link api chat sms_reply manual |
Response (200 OK)
{
"status": "acknowledged",
"acknowledged_at": "2026-03-14T12:03:22Z",
"acknowledged_via": "api"
}Severity Levels
AgentPing uses a voice-first model. All severities default to phone calls with escalation retries.
| Severity | Delivery | Escalation behavior |
|---|---|---|
| normal | Voice call | Phone call with retries (2 min apart). Respects quiet hours. Press 0 to acknowledge, 1 to snooze 5 min, or enter 2-120 followed by # for custom snooze. |
| critical | Voice call (bypasses quiet hours) | Immediate phone call with retries. Bypasses quiet hours — use for alerts that cannot wait until morning. |
low, urgent, and persistent_critical are still accepted for backwards compatibility. low and urgent map to normal; persistent_critical maps to critical.
Alert Types & Templates
Alert types set sensible default escalation timing. You can override the delay with delay_seconds.
| Alert Type | Default Delay | Best for |
|---|---|---|
| approval | 300s (5 min) | Agent needs a decision before proceeding |
| task_failure | 120s (2 min) | Something broke and needs attention |
| threshold | 600s (10 min) | A metric or condition crossed a boundary |
| reminder | 300s (5 min) | Time-sensitive nudge or follow-up |
| other | 0s (immediate) | General escalation |
When delay_seconds is set (or defaulted) to a value greater than 0, the alert enters a waiting_for_primary_ack state. During this window, if the user acknowledges via chat or API, no call is placed. This is the "chat first, then escalate" pattern.
Alert Lifecycle
An alert transitions through these states from creation to resolution:
created
│
├── delay_seconds > 0 ──► waiting_for_primary_ack
│ │
│ ack within delay?
│ ┌──yes──┘ └──no──┐
│ ▼ ▼
│ acknowledged escalating_call (voice-first)
│
├── delay_seconds = 0 ──► escalating_call
│
▼
escalating_call ──► user picks up
│ │
│ ┌──────┼──────┐
│ ▼ ▼ ▼
│ ack(0) snooze no answer
│ │ │ │
│ ▼ ▼ ▼
│ acknowledged snoozed retry
│ │ │
│ └──►───┘
│ escalating_call
▼
expired (TTL elapsed)
failed (delivery error / retries exhausted)Status values
| Status | Description |
|---|---|
| created | Alert created, awaiting processing |
| waiting_for_primary_ack | Waiting for delay_seconds before escalating — ack now to prevent call |
| escalating_sms | SMS delivery in progress |
| escalating_call | Voice call in progress or awaiting retry |
| snoozed | User snoozed via DTMF — a new call is scheduled after the snooze period |
| delivered | Delivery completed (no further escalation) |
| acknowledged | User acknowledged — escalation stopped (terminal) |
| expired | TTL elapsed without acknowledgement (terminal) |
| failed | Delivery failed permanently (terminal) |
Phone Number Targeting
By default, alerts are delivered to your primary verified phone number. You can target a specific number by passing the phone_number field in the request body.
| Scenario | Behavior |
|---|---|
phone_number omitted | Delivered to your primary verified phone. If no primary is set, falls back to any verified phone on your account. |
phone_number provided | Must be in E.164 format (e.g. +14155550123) and already verified on your account. Returns 422 if the number is not verified. |
| No verified phone on account | Returns 422 — add and verify a phone number first. |
AgentPing only delivers to your own pre-verified numbers. This prevents misuse and ensures you control which phones receive alerts.
Acknowledgement Methods
Any acknowledgement immediately stops further escalation for that alert. There are six ways to acknowledge:
| Method | How it works | When used |
|---|---|---|
| dtmf | Press 0 on your phone keypad during the voice call | During an active call |
| sms_link | Tap the acknowledgement link in the SMS message | After receiving an SMS alert |
| api | Call POST /v1/alerts/{id}/acknowledge with your API key | Agent or automation acknowledges programmatically |
| chat | Your agent calls the acknowledge endpoint after the user responds in chat | User responds in the agent's chat interface during the delay window |
| sms_reply | Reply 1, ack, or yes to the AgentPing SMS | After receiving an SMS alert on supported plans |
| manual | Acknowledged from the AgentPing dashboard | User views alert history and manually marks it |
The acknowledged_via field in the alert response records which method was used. If an alert is already acknowledged or in a terminal state (expired, failed), subsequent acknowledge calls are no-ops.
Quiet Hours & Policy
AgentPing respects your notification preferences. Configure these in your dashboard.
Channel toggles
You can enable or disable voice calls. If voice is disabled, alert creation returns an error since there is no valid delivery path.
Quiet hours
Set a quiet hours window (e.g. 22:00–07:00 in your timezone) to suppress voice calls for non-critical alerts. During quiet hours:
| Severity | Quiet hours behavior |
|---|---|
| normal | Voice call steps are suppressed. Alert is logged but no call is placed. |
| critical | Bypasses quiet hours. Voice calls are delivered normally — these alerts are too important to defer. |
Emergency stop
The emergency stop toggle in your dashboard immediately blocks all alert creation (returns 403). Use it to silence everything instantly. Disable it when you're ready to resume.
Metadata
The metadata field accepts an arbitrary JSON object that is stored with the alert and returned in all responses. Use it to attach context from your agent that helps you act on the alert.
{
"title": "Build failed",
"severity": "critical",
"alert_type": "task_failure",
"metadata": {
"task_id": "build-7823",
"repo": "acme/api",
"branch": "main",
"log_url": "https://ci.example.com/builds/7823"
}
}Common uses: task IDs, URLs, environment names, error codes, or any data your agent needs to reference when the user responds. The field is optional and has no enforced schema — pass whatever key-value pairs are useful for your workflow.
Rate Limits
Rate limits protect against runaway agents and accidental loops.
| Limit | Window | Scope |
|---|---|---|
| 20 alerts | Per hour | Per user (across all API keys) |
| 10 alerts | Per hour | Per individual API key |
Monthly quotas by plan
| Resource | Free | Starter ($9/mo) | Pro ($29/mo) |
|---|---|---|---|
| Escalated alerts / month | 10 | 300 | 2,000 |
| Call minutes / month | 5 | 120 | 500 |
| Max retries per alert | 1 | 5 | 10 |
| Verified phones | 1 | 3 | 10 |
| Voice message | Custom (title + message) | Custom (title + message) | Custom (title + message) |
| Quiet hours | No | Yes | Yes |
The free plan has no time limit — only quota limits. Alerts acknowledged during the chat delay (before escalation) do not count against your quota. Exceeding a monthly quota returns a 403 error.
Error Responses
All errors return a JSON object with a detail field.
| Status | Meaning | Example detail |
|---|---|---|
| 401 | Unauthorized | "Missing X-API-Key header""Invalid API key""API key has been revoked" |
| 403 | Forbidden | "Emergency stop is active...""Your 14-day free trial has expired...""Monthly SMS quota exceeded" |
| 404 | Not Found | "Alert not found" |
| 422 | Validation Error | [{"loc": ["body", "severity"], "msg": "Input should be..."}] |
| 429 | Rate Limited | "Rate limit exceeded: 20 alerts per hour""Rate limit exceeded: 10 alerts per hour per key" |
Ready to get started?
Create an account, verify your phone, and generate an API key.