Skip to content

Approve or deny, from your phone

Your script needs a human decision. Send it as an interactive task with choices; the answer comes back in seconds. No polling, no webhook to host.

Good for: AI agents that need approval before touching production, deploy bots, oncall triage, any "pause until a human weighs in" flow.

bash
sp task -t deploys --title "Deploy to production?" \
  -c "Commit abc123 is ready;Approve,Deny,Hold" \
  --wait
python
import asyncio
from simplepush import Client, ChoiceInput, TaskCompleted

client = Client(api_token="YOUR_API_TOKEN")

group = client.send_task(
    topic="deploys",
    title="Deploy to production?",
    content="Commit abc123 is ready",
    inputs=[ChoiceInput(options=["Approve", "Deny", "Hold"])],
)

async def main():
    async for g in group.inputs(timeout=600):
        if isinstance(g.item, TaskCompleted):
            print("User chose:", g.item.uploads[0].value)
            break
    await client.aclose()

asyncio.run(main())
ts
import { Client } from '@simplepush/sdk'

const client = new Client({ apiToken: 'YOUR_API_TOKEN' })

const group = await client.sendTask({
  topic: 'deploys',
  title: 'Deploy to production?',
  content: 'Commit abc123 is ready',
  inputs: [{ type: 'choice', options: ['Approve', 'Deny', 'Hold'], required: true }],
})

for await (const { item } of group.inputs({ idleMs: 600_000 })) {
  if (item.kind === 'taskCompleted') {
    const choice = item.uploads.find((u) => u.kind === 'choice')
    console.log('User chose:', choice?.value)
    break
  }
}
client.close()
bash
ANSWER=$(curl -s -X POST https://api.simplepu.sh/v1/tasks \
  -H "API-Token: $SP_API_TOKEN" \
  -H "Topic: deploys" \
  -H "Title: Deploy to production?" \
  -H "Choice-Input: Commit abc123 is ready;Approve,Deny,Hold" \
  -H "Wait: true" | tr -d '\n')

echo "User chose: $ANSWER"

A single-select choice renders as tappable buttons on the push notification, so answering doesn't require opening the app.

The --wait flag and the Wait: true header block until the first answer, which is perfect for quick approvals. For anything longer-lived, collect over a resumable stream instead: pipe the send into sp collect (sp task ... --format json | sp collect) or use the SDK streams shown above.