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
- No access to your cloud provider, CI/CD, or deploy credentials.
- No access to the contents of the actions your agent takes — only the title/details text you
explicitly pass to
request_approvalornotify. - No password-based login for operators — answer links are signed and single-purpose; the dashboard uses magic-link email.
Who's accountable, and what happens if something goes wrong
pendnt is built and operated day to day by an autonomous AI agent (Claude). That's true, and it's a fair question to stop and ask "so who do I actually escalate to." The answer:
- Accountable party: Kade Angell, the human owner, is the operator of record — named, with a mailing address, in §1 of the Terms of Service. The autonomous agent building and running pendnt doesn't change who's legally and practically responsible for it; it's the same as if the work were done by a human employee.
- How to reach a human: arkade523@gmail.com — the same address listed as the legal contact in the Terms and Privacy Policy. It reaches Kade directly, not a queue.
- What the autonomous operator can do unilaterally: ship code, deploy, monitor the service, answer routine support questions, and act on the policies already written down on this page and in the Terms — the same latitude you'd give an on-call engineer.
- What it can't: change the Terms of Service or this Security page's substantive commitments, move money (billing runs through Stripe's own dashboard/portal, not anything the agent can unilaterally touch), or make a one-off exception to the account/data handling described here. Those require the human owner.
- Incident handling: a material incident (data exposure, extended outage, anything that would change what's written on this page) gets a dated note on the changelog — which doubles as the build log — and a direct email to every account we believe was affected. We don't currently have a separate status page; the changelog is the status note until one exists.
- Compliance, honestly: no SOC 2 or other third-party audit yet. pendnt is an early-stage service — what's on this page is the real, current state of things, not a compliance-program summary. If SOC 2 becomes something customers need to move forward, it's a roadmap item we'd take on then, not something we're claiming now.
Reporting an issue
If you find a security issue, please report it via email rather than a public issue — we'll acknowledge and follow up. Fixes and any disclosures are noted in the changelog.