Security

pendnt only ever sees one credential from your agent: an API key scoped to your workspace. Here's exactly what that key can do, how the other unauthenticated URLs are protected, and what we deliberately never ask for.

API keys

Every workspace has one or more API keys in the form aio_<32 base62 chars>, generated with a cryptographically secure random source. We store only a SHA-256 hash of the key plus a short prefix (for fast lookup before a constant-time hash comparison) — the full key is shown once, at creation time, and never again. A key authenticates as Authorization: Bearer <key> and is scoped to exactly one workspace; it cannot see or act on any other workspace's data.

Rotate a key by creating a new one and revoking the old one from the dashboard. There is no "master" key that spans workspaces.

Do you see my secrets?

No. The agent's only credential to us is our own API key, scoped to your workspace. We never ask for — and have no use for — your cloud credentials, deploy keys, or any secret the agent uses to do its actual work. pendnt sits entirely outside your deploy/production path: it relays a question and a human's answer, nothing more.

Inbound endpoints

https://api.pendnt.dev/in/<slug> URLs are intentionally unauthenticated by default — that's what lets a third party (GitHub, Stripe, an OAuth provider) POST to them without your agent having to hand out an API key. Protection instead comes from the slug itself being an unguessable random identifier, plus an optional per-endpoint secret: create an endpoint with require_token: true and every request to it must include ?token=<secret> or an X-Endpoint-Token: <secret> header, or it's rejected with 403. Each endpoint's secret is independent — leaking one doesn't expose any other endpoint or your API key.

Signed operator answer links

When a request goes out to a channel (email, Telegram, etc.), the link an operator taps to answer it — https://api.pendnt.dev/a/<request_id>/<sig> — requires no login. sig is base64url(HMAC-SHA256(request_id, SIGNING_SECRET)), verified in constant time. Anyone with the exact link can answer that one request; the signature can't be forged without the workspace's signing secret, and it doesn't grant access to anything else — not other requests, not the REST API, not the dashboard.

Inbound webhook payloads

Requests to /in/<slug> are stored as events: method, path, query params, headers (hop-by-hop and Cloudflare-internal headers stripped before storage), and body (up to 256KB — stored as text when it decodes cleanly as UTF-8 and looks textual, base64 otherwise). These events are only readable via your workspace's API key (wait_for_event / GET /v1/events).

Outbound webhook signing

When pendnt delivers to a webhook channel you've configured, the request body is signed with X-Pendnt-Signature: <hmac> — HMAC-SHA256 over the raw body, using that channel's own secret if you set one, otherwise your workspace's signing secret. Verify it before trusting the payload, the same way you'd verify any inbound webhook.

Rate limiting

600 requests/minute per API key, enforced independently of your plan, to absorb abuse and runaway loops rather than to bill precisely — see Pricing for the plan-level limits (requests/month, retention, endpoints).

Infrastructure

pendnt runs entirely on Cloudflare: Workers for the API and MCP server, D1 as the source of truth for accounts/workspaces/requests/events, a Durable Object per workspace for long-poll coordination and scheduled-wakeup alarms, KV for rate-limit counters, and Queues for channel delivery. There is no separate database or server outside Cloudflare's network holding your data.

What we don't have

Reporting an issue

If you find a security issue, please report it via the contact link on the dashboard rather than a public issue — we'll acknowledge and follow up. Fixes and any disclosures are noted in the changelog.

Early access — launched August 2026.