Changelog
What changed, newest first
Dashboard features, API additions, security hardening and documentation updates, written for the people using the product. Breaking API changes are called out here before they ship.
Updated October 2, 2026API reference · openapi.json · RSS feed
- DashboardAPISecurity
Teams and roles, named API keys with scopes, webhook endpoints
- Invite teammates from the new Team page. Owners manage billing, ownership and deletion; admins manage approvers, API keys, webhooks and members; members can view approvals, approvers, stats and usage. Invite links (/invite/<token>) work for 7 days and only for the invited address; the page explains an expired link, a mismatched email (with a sign-out button) or an account that already has a workspace. Someone invited before they sign up is taken straight to their invite on first login.
- API keys are now named and scoped: create as many as 20 per workspace on the API keys page, each with approvals:write and/or approvals:read and an optional expiry (30, 90 or 365 days). The full key is shown once; the list shows the prefix, scopes, creation, last use, expiry and status, and revoked keys stay listed for 30 days. A key used outside its scope gets 403 insufficient_scope. The old rotate-everything action lives on under Settings → API key → Advanced.
- Webhook endpoints: add up to ten https:// URLs on the Webhooks page and every approval.decided decision is delivered to each enabled endpoint, signed with its own whsec_… secret (shown once, rotatable) and tagged with X-Approv-Delivery. Send a signed test event, enable or disable an endpoint, and browse the Deliveries log — request body, response status, error and attempts, filterable by endpoint, status and approval — with one-click replay. The callback_url you pass per request keeps working and its secret stays under Settings → Webhooks as the legacy callback_url secret.
- The sidebar gains Team, API keys and Webhooks under Configure; members do not see the last two. Every new route is in /openapi.json and the docs, marked x-approv-status: phase-c until the backend is verified against it.
- DashboardAPISecurity
Server-side filters, exact month stats and per-project webhook secrets
- The Approvals page now filters and searches on the server: the status segments (including Approved and Rejected) and the search box go to GET /?status=&q=, and Load more follows next_cursor, so large projects browse without downloading everything. Decided rows show their outcome as a pill. Date presets still apply to the rows on screen.
- The Overview's Activity card reads GET /account/stats — exact figures for the whole month at any volume, with the seven-day sparkline from the same source — and no longer needs your API key pasted to show numbers.
- Settings has a Webhooks card: reveal and copy your project's whsec_… signing secret, rotate it behind a confirmation (the old secret stops verifying immediately), and see how to verify a delivery. The webhook body now also carries status, action, params_hash, approver_id, amount and currency.
- The API key card shows the key's identifier, when it was created and when it was last used. Rotating more than five times a minute is refused with the exact number of seconds to wait.
- Hitting your monthly quota is explained in place: a 402 quota_exceeded from the test send shows the plan, its limit and what you have used, with an Upgrade link; a 429 shows a Retry-After countdown.
- Approvers have a language (English or Arabic) shown as a chip and chosen when you add them; the opt-in page records the language the approver confirmed in.
- APIDocs
Docs and verifier checked against the backend source
- The offline audit verifier (/verify-audit.mjs) now reproduces the backend's bytes exactly: the four hashed fields are joined with U+241F (the ␟ character named by algorithm.field_separator, not a literal |), seq starts at 0, the first prev_hash is 64 zeros, and the signature is base64 Ed25519 over the hex hash string. Earlier builds of the script rejected every real trail; it is now tested against a trail produced by the backend's own audit engine.
- Idempotency-Key is supported on POST /: a retry with the same key returns the original approval with replayed: true and is not charged to your quota. The docs previously said no idempotency key existed.
- The create body is documented as the backend validates it: action, approver_id (uuid), amount, currency, context, params_hash, callback_url, locale (en | ar), timeout_seconds (default 3600, max 86400) and metadata. There is no expires_in_seconds.
- Status responses document params_hash, locale, updated_at and the real decided_via values (whatsapp_button, whatsapp_text, sms_reply, web_link, console, api); list responses document count and the row fields. The webhook body is exactly { id, outcome, decided_via, decided_at } with an X-Approv-Event header.
- Error codes are the ones the backend emits — unauthorized, validation_error (with details), not_found, rate_limited, internal_error — plus 402 quota_exceeded arriving in API build 2026-10. invalid_api_key and approver_not_opted_in never existed and are gone.
- API keys are shown in their real format, apk_live_<8 hex>_<secret>; the dashboard identifies a key by its apk_live_<8 hex> prefix.
- Dashboard
Approval detail pages and an activity overview
- Every approval now has its own page at /app/approvals/:id with status, amount, channel, approver, decision timestamps, a copy-link button and the full verified audit trail. Rows in the approvals table link straight to it.
- Download the signed audit trail as JSON from the detail page to keep a copy that verifies without us.
- The Overview shows an Activity card once setup is complete: approvals this month, approval rate, median time to decision, how many are pending right now, and a seven-day sparkline.
- The onboarding steps collapse into a one-line summary when you are done with them.
- APIDocs
OpenAPI 3.1 spec and a fuller API reference
- The whole API is now described in an OpenAPI 3.1 document at /openapi.json, including the approval.decided webhook. Generate a typed client, mock the API in tests or browse it in any OpenAPI viewer.
- New reference sections: List approvals, Verify a webhook (Node and Python), Verify the audit trail offline, Idempotency, Rate limits & quotas, and SDKs.
- Corrections: the documented base URL is your Supabase functions host plus /approvals; 402 quota_exceeded is listed with the other error codes.
- Fields we documented from the product rather than the backend source were marked x-approv-inferred in the spec; see the later entry on checking the spec against the backend.
- DashboardSecurity
Account self-service
- A new Account page at /app/account shows your email, user id and sign-up date.
- Change your password (you re-enter the current one first) or your email address without contacting support.
- Sign out of every device at once.
- Delete your account with a two-step confirmation that requires typing your email.
- DashboardBilling
Usage meter and quota warnings
- Settings and the sidebar show how many approvals you have used this month against your plan's quota.
- A warning appears at 80% of the quota, and a clear alert at 100% explaining that new approvals are rejected with 402 until you upgrade.
- The pricing page now says exactly what you get: no free-trial claim, Growth upgrades from inside the app, and Scale items that need a conversation are marked on request. A short FAQ answers what counts as an approval and what happens at the limit.
- New /contact page for Scale conversations: volume, retention, dedicated key signing and compliance questions go to sales@ai-approvel.com.
- Security
Server-side sign-in and hardened headers
- Sessions are now kept in secure cookies and checked on the server before any /app page loads. Signed-out visitors are sent to the login page and brought back to where they were going afterwards.
- Links in sign-up and password-reset emails go through /auth/callback, which exchanges the one-time code for a session.
- Every response carries a strict Content-Security-Policy, HSTS with preload, X-Frame-Options DENY, a Referrer-Policy and a Permissions-Policy.
- Existing users sign in once more after this change; nothing else is required.
- SecurityAPIDashboard
API keys are shown once
- The full API key is displayed a single time, when you generate or rotate it. Afterwards the dashboard shows only the key prefix so you can tell keys apart.
- The key is no longer stored in the browser. Returning to the dashboard in a fresh session, paste your key to view approvals or send a test; it is kept in memory for that session only.
- Nothing rotates your key automatically anymore. Rotation is an explicit action with a confirmation that warns your integrations will get 401 until updated.
- Requests with a rotated or unknown key return 401, and the dashboard tells you the key is invalid instead of failing silently.
- DashboardSecurity
Error monitoring and a disclosure policy
- If something breaks, the error page shows a reference id you can quote to support so we can find exactly what happened.
- Errors are reported to our monitoring with authorization headers, cookies and key or token query values scrubbed. Session replay is off and no personal data is collected.
- SECURITY.md explains how to report a vulnerability to us responsibly.
- DocsDashboard
Approv is now AI Approvel
- The product, the site and the dashboard are now AI Approvel at ai-approvel.com, with a new mark and favicon.
- Nothing changes for integrations: your API keys, the approvals API and the X-Approv-Timestamp and X-Approv-Signature webhook headers are unchanged.
- SecurityAPI
Tap-to-confirm approval links
- Approval links in WhatsApp and SMS messages open a confirmation page. The decision is recorded only when the approver taps the button, so link previews, security scanners and other bots that follow URLs can no longer approve or reject on someone's behalf.
- SecurityAPI
Independent security review
- callback_url must be https:// and resolve to a public host; private, loopback, link-local and cloud-metadata addresses are rejected when the approval is created and again when the webhook is sent.
- Monthly quota enforcement is now atomic, so parallel requests at the limit can no longer slip past it.
- The reviewer confirmed billing webhook signatures, tenant scoping, API-key hashing, CORS and email escaping as safe.
- APISecurity
Signed webhooks
- Pass a callback_url when creating an approval and we POST the decision to it, so your agent can continue without polling.
- Every delivery is signed: X-Approv-Signature is the HMAC-SHA256 of the timestamp and raw body, and X-Approv-Timestamp lets you reject replays.
- Failed deliveries are retried with backoff, and each attempt is recorded in the approval's audit trail as webhook.delivered or webhook.failed.
- API
Rate limits
- Each project may create up to 60 approvals per minute (only POST / is limited; reads are free). Past that you receive 429 rate_limited with a Retry-After header saying how long to wait.
- Need more? Contact us and we raise the limit for your project.
- BillingDashboard
Plans, billing and monthly quotas
- Three plans: Free (100 approvals a month), Growth (5,000) and Scale (custom). Reads never count against the quota.
- Creating an approval past your monthly quota returns 402 quota_exceeded with an upgrade link; usage resets on the first of the month.
- Settings has a Plan & billing card: upgrade through checkout and manage your subscription in the billing portal. Current-month usage is shown next to it.
- Dashboard
Email notifications for decisions
- Project owners receive an email when an approver decides, in addition to the webhook. Each decision is emailed once, even if the webhook is retried.
- Dashboard
Export, search and filters for approvals
- Search approvals by action text, filter by status with one tap, and load more as you scroll back in time.
- Export the current view as CSV or JSON; the export respects the filters you have applied.
- Approval details show per-event timestamps, full hashes with a copy button and a 'Verify this yourself' panel with the hash formula and public key.
- Dashboard
Dark mode
- A dark theme for the site and the dashboard, toggled from the header or sidebar. Your choice is remembered on this device and applied before the page paints, so there is no flash.
Missing something you rely on? Tell us or write to support@ai-approvel.com.