Pause Requests
The pause_request is the core entity in PausePoint. Creating one pauses your agent, sends a notification, and waits for a human response.
Status State Machine#
┌─────────────────────────────────────────┐
│ CREATE │
│ POST /v1/pause │
└──────────────┬──────────────────────────┘
│
▼
┌─────────┐
│ pending │ ◄── polling happens here
└────┬────┘
│
┌────────────────┼────────────────┐
│ │ │
▼ ▼ ▼
┌──────────┐ ┌───────────┐ ┌───────────┐
│responded │ │ timed_out │ │ cancelled │
└──────────┘ └───────────┘ └───────────┘
Once a request leaves pending, it cannot change status again.
Create a Pause Request#
POST /v1/pause
Request Fields#
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
recipient |
string | Yes | · | Phone (E.164), Telegram chat ID, email address, or Slack webhook URL |
channel |
string | Yes | · | "sms" | "email" | "slack" | "telegram" |
message |
string | Yes | · | The question shown to the human. Max 2000 chars. |
options |
string[] | Yes | · | 2–5 answer choices. e.g. ["Approve", "Reject"] |
allow_text_response |
bool | No | false | Show a freetext note input on the response page |
timeout_hours |
int | No | 24 | Hours before auto-timeout. Capped by plan. |
timeout_default |
string|null | No | null | Option to auto-select on timeout. null = no auto-choice. |
metadata |
object | No | null | Arbitrary key-value data. Returned in webhooks and polls. |
Channel-Specific Recipient Formats#
| Channel | Recipient format | Example |
|---|---|---|
| sms | E.164 phone number | "+15550100" |
| telegram | Numeric chat ID (message the bot first to get yours) | "123456789" |
| Email address | "cfo@company.com" |
|
| slack | Slack incoming webhook URL | "https://hooks.slack.com/services/..." |
Example · SMS#
curl -X POST https://api.pausepoint.dev/v1/pause \
-H "Authorization: Bearer $PP_KEY" \
-H "Content-Type: application/json" \
-d '{
"recipient": "+15550100",
"channel": "sms",
"message": "Your agent wants to send a $340 wire to Acme Corp. Approve?",
"options": ["Approve", "Reject"],
"timeout_hours": 4,
"timeout_default": "Reject",
"metadata": {"amount": 340, "recipient_name": "Acme Corp"}
}'
Example · Email#
curl -X POST https://api.pausepoint.dev/v1/pause \
-H "Authorization: Bearer $PP_KEY" \
-H "Content-Type: application/json" \
-d '{
"recipient": "cfo@company.com",
"channel": "email",
"message": "The sales agent has drafted a campaign email to 200 leads. Send it?",
"options": ["Send it", "Edit first", "Cancel"],
"timeout_hours": 24,
"timeout_default": "Cancel"
}'
Example · Slack#
curl -X POST https://api.pausepoint.dev/v1/pause \
-H "Authorization: Bearer $PP_KEY" \
-H "Content-Type: application/json" \
-d '{
"recipient": "https://hooks.slack.com/services/T.../B.../...",
"channel": "slack",
"message": "Delete 14,000 stale user records from the test environment?",
"options": ["Delete", "Keep", "Ask me tomorrow"],
"timeout_hours": 8
}'
Wait for the Response#
GET /v1/pause/{pause_id}/wait?timeout=60
The easiest way to get the outcome: a long-poll that blocks until the pause is resolved (responded, timed out, or cancelled), then returns its full state. If nothing has happened after timeout seconds (1 to 120, default 60), it returns the current pending state; call it again to keep waiting.
import requests
while True:
result = requests.get(
f"https://api.pausepoint.dev/v1/pause/{pause_id}/wait",
params={"timeout": 120},
headers={"Authorization": f"Bearer {api_key}"},
timeout=130,
).json()
if result["status"] != "pending":
decision = result["response_choice"] # "Approve", or timeout_default
break
One request replaces a polling loop, and your agent resumes within about 2 seconds of the person acting.
Poll for Response#
GET /v1/pause/{pause_id}
A single non-blocking status check, if you'd rather manage the loop yourself (or check from a cron job):
import requests, time
while True:
result = requests.get(
f"https://api.pausepoint.dev/v1/pause/{pause_id}",
headers={"Authorization": f"Bearer {api_key}"}
).json()
if result["status"] == "responded":
decision = result["response_choice"] # "Approve"
break
elif result["status"] in ("timed_out", "cancelled"):
decision = result["response_choice"] # timeout_default or None
break
time.sleep(5)
Response Fields#
| Field | Type | Description |
|---|---|---|
pause_id |
UUID | Unique identifier |
status |
string | pending | responded | timed_out | cancelled |
response_choice |
string|null | The human's choice (or timeout_default) |
response_text |
string|null | Freetext note if allow_text_response was true |
response_at |
ISO timestamp|null | When the response was recorded |
expires_at |
ISO timestamp | When timeout fires |
metadata |
object|null | Whatever you passed in |
Metadata Field#
Pass any JSON object in metadata. It is returned unchanged in every poll response and webhook payload. Use it to correlate responses with your internal state:
{
"metadata": {
"agent_run_id": "run_abc123",
"customer_id": "cust_9876",
"amount_usd": 340
}
}