Skip to documentation
Notify Docs

Ask for a decision

Pause work for a person’s approval, choice, or reply. Creating a prompt is the beginning of that exchange; use its confirmed server outcome to decide what happens next.

Ask and wait in the terminal

Use notify send ask <prompt> when later work depends on an answer. Select one of --approval, --yes-no, or --text; ordinary send appearance flags also apply. The example asks whether a package should be held for collection.

bash
notify send ask "Hold package PKG-42 until tomorrow?" \
  --approval --title "Warehouse desk" --wait --timeout 15m

For approval or yes/no, --live-activity requests an iOS interactive card (iOS 17+) with approval, shell, verdict, or signal style. Native Android receives an ordinary actionable alert for this presentation. The prompt is limited to 240 characters, labels to 1–24 characters, and expiry to eight hours. This presentation accepts no text replies, images, or URLs. Custom primary/secondary labels change displayed verbs; returned actions remain canonical.

bash
notify send ask "Send the pickup reminder?" \
  --approval --live-activity --style signal \
  --primary-label Send --secondary-label Deny \
  --wait --timeout 15m

--wait waits for a terminal answer, subject to --timeout (by default, the requested prompt expiry: 15 minutes unless changed). --poll waits up to 20 seconds. Either wait may time out while the prompt stays pending; neither cancels it. Prompt expiry defaults to 15 minutes and is set separately with --expires-in. Resume with notify interaction wait <id>; that standalone command defaults to a 60-second wait. A pending interaction get can exit successfully, so do not treat a successful read as approval.

json
{
  "interaction": {
    "id": "int_7MFuml-SqoUmpPLo",
    "kind": "reply",
    "status": "replied",
    "response": "Leave it at the desk",
    "respondedAt": "2026-10-12T11:54:17.927Z"
  },
  "accepted": 1,
  "timedOut": false
}

Ask from a webhook

For a webhook question, include response next to the message. Choose approval for Approve/Deny, yes_no for Yes/No, or text for a typed reply. The warehouse example asks whether a delayed parcel should be held.

json
{
  "title": "Warehouse pickup",
  "body": "Hold package PKG-42 for collection?",
  "response": {
    "type": "approval",
    "expiresInSeconds": 900,
    "correlationId": "pickup-42",
    "callback": {
      "url": "https://warehouse.example.com/notify-answer",
      "token": "callback_token_placeholder_32_chars"
    }
  }
}
Interactive response fields
FieldTypeDescription
typestring, requiredRequired choice of approval, yes_no, or text.
expiresInSecondsintegerAnswer window: integer from 30 to 86,400 seconds; default 900.
correlationIdstringOptional sender-defined correlation value, maximum 100 characters, echoed in the callback.
callback.urlstringClassic answered-callback destination. Requires public HTTPS and a paired callback token.
callback.tokenstringClassic callback bearer credential and HMAC key, 16–512 characters.
callback.targetobjectConnector destination { connectorId, route, path }; use instead of callback.url/token. See the connector receiver guide.
webhookIdstringAccount-owned saved reply webhook ID (whk_…) selected for this interaction, in addition to applicable service/account defaults.

A successful question send adds pending-response metadata. Store the event ID and deadline; acceptance of the push does not authorize the requested action.

json
{
  "ok": true,
  "eventId": "evt_example_pickup",
  "delivered": 1,
  "response": { "status": "pending", "expiresAt": "2026-10-11T18:19:04.000Z" }
}

Read or cancel the outcome

Read the saved event ID to find a webhook question’s current outcome. To stop accepting answers before its deadline, POST to /cancel. Canceling the question and withdrawing the displayed notification are separate operations.

bash
curl https://notify.belweave.ai/hooks/whk_your_token/events/evt_example_pickup

curl -X POST https://notify.belweave.ai/hooks/whk_your_token/events/evt_example_pickup/cancel
json
{
  "ok": true,
  "event": {
    "id": "evt_example_pickup",
    "response": {
      "status": "approved",
      "action": "approve",
      "text": null,
      "correlationId": "pickup-42",
      "respondedAt": "2026-10-11T18:06:52.000Z",
      "expiresAt": "2026-10-11T18:19:04.000Z"
    }
  }
}
  • pending means no settled answer. Terminal statuses are approved, denied, yes, no, replied, expired, and canceled.
  • A text answer has action: "reply" and a populated text; choice answers carry the selected canonical action and text: null.
  • Reading an overdue pending question settles it as expired.
  • Only pending responses can be canceled; other states return 404 from cancel. The webhook can only inspect events belonging to its service.
An offline client may queue an answer locally. Queued is not server-confirmed: another valid answer, expiry, cancellation, or removal of access can win before synchronization. Continue automation only after the server reports the required terminal outcome.

Route agent permission requests

Permission hooks let Claude Code, Codex, and OpenCode V1/V2 pause for a person’s decision. A grant requires an explicit, valid approval and applies once. Denial, timeout, invalid input, authentication or network errors, and no accepted or queued device delivery all deny the request. Queued delivery keeps waiting; only a server-confirmed explicit approval grants permission.

bash
notify permissions setup all
notify permissions doctor

Keep notifications:send, interactions:create, and interactions:read on the connection. The default login includes them; narrowed logins must request them. Setup and permissions doctor check scopes before installing hooks.

Install one integration with permissions setup claude, codex, or opencode. Codex also requires review/trust in /hooks. On macOS, OpenCode setup installs its V1 plugin and V2 background connector. notify permissions uninstall all removes Notify-owned hooks and services.

The phone receives a limited request summary: agent name, permission/tool name, project-directory basename, and resource count. It does not receive raw commands, patches, prompts, file contents, URLs, environment values, transcript paths, or absolute paths.