curl / plain scripts

It's a REST API underneath everything else — no SDK required. This walkthrough matches the REST reference exactly.

BASE=https://api.pendnt.dev
KEY="$PENDNT_API_KEY"   # from https://api.pendnt.dev/signup

# 1. Create an inbound endpoint and send it a webhook
EP=$(curl -s -X POST "$BASE/v1/endpoints" \
  -H "authorization: Bearer $KEY" -d '{"name":"gh"}')
SLUG=$(echo "$EP" | jq -r .slug)

curl -s -X POST "$BASE/in/$SLUG" \
  -H 'content-type: application/json' -d '{"hello":"world"}'

curl -s "$BASE/v1/events" -H "authorization: Bearer $KEY" | jq

# 2. Ask for an approval and long-poll for the answer
curl -s -X POST "$BASE/v1/requests" -H "authorization: Bearer $KEY" \
  -d '{"kind":"approval","title":"Deploy to prod?","wait_s":25}'

# 3. Fire-and-forget notification
curl -s -X POST "$BASE/v1/notify" -H "authorization: Bearer $KEY" \
  -d '{"message":"build finished"}'

# 4. KV scratchpad
curl -s -X PUT "$BASE/v1/kv/last_run" -H "authorization: Bearer $KEY" \
  -d '{"value":"2026-08-29T00:00:00Z"}'
curl -s "$BASE/v1/kv/last_run" -H "authorization: Bearer $KEY"

# 5. Schedule a wakeup 60s out
curl -s -X POST "$BASE/v1/wakeups" -H "authorization: Bearer $KEY" \
  -d '{"in_s":60,"payload":{"check":"status"}}'

Blocking vs. resumable

Step 2 above passes wait_s: 25, so the call blocks for up to 25 seconds waiting for an operator to answer (from the web inbox, email, or any connected channel). If it's still pending after that, re-poll the same request instead of creating a new one:

RID="req_..."   # the "id" from the create-request response

curl -s "$BASE/v1/requests/$RID?wait_s=25" -H "authorization: Bearer $KEY"

The request stays open (durable) for timeout_s seconds regardless — default 86400 (24h) — so a script can poll again minutes or hours later with the same id and still get an answer.

Answering from a script (testing)

In production, the link an operator taps comes from a delivery channel (email, Telegram, etc.) — see Channels. For local testing or scripted answers, the answer endpoint just needs a valid request_id + signature pair:

curl -X POST "$BASE/a/$RID/$SIG" \
  -H 'content-type: application/json' \
  -d '{"action":"approve"}'

action is approve, deny, or answer (with an optional text field) — see the operator answer page reference. The signature is workspace-specific and not something you compute client-side in production; it's handed to you pre-signed inside each delivered link.

Cancel a pending request

curl -s -X POST "$BASE/v1/requests/$RID/cancel" -H "authorization: Bearer $KEY"

List and cancel a wakeup

curl -s "$BASE/v1/wakeups" -H "authorization: Bearer $KEY" | jq

WID="wkp_..."
curl -s -X DELETE "$BASE/v1/wakeups/$WID" -H "authorization: Bearer $KEY"

Every route used above, plus errors and rate limits, is documented in full in the REST reference.

Early access — launched August 2026.