Secret header
Default. Callers send X-SnipVault-Secret or Authorization: Bearer. Compared with hash_equals. Settings saves cannot plant a weak secret — only Rotate can change it.
Expose a published PHP snippet as a signed inbound endpoint at /sv/your-slug. Secret-header auth, rate limits, invocation logs, and an agent that can author the handler — without a custom plugin or admin-ajax.
/sv
Pretty permalink
4
Auth modes
50
Invocation logs
1 MB
Max payload
stripe-webhook.php
/sv/stripe-webhook
POST/sv/stripe-webhook
X-SnipVault-Secret••••••••••••••••
Last invocations
New in v1.3.2
Functions are not a second product. They are PHP snippets with an inbound door: HMAC-signed files, the same audit ceiling, and a log you can replay after a vendor retries.
How it works
The Function card lives on PHP snippets. Enable it, publish, and the isolated runner accepts HTTP without loading the rest of your library into that request's job.
01
Create a PHP snippet that reads $snipvault_function for method, JSON body, headers, query, and IP. Guard the file so a normal page-load or sandbox probe is a no-op. Return status, headers, and body — not a printed dump of $_POST.
02
Flip Enable as function, set a slug, pick GET and/or POST, and choose auth. SnipVault generates a rotate-only secret, unique-ifies the slug, and prints the /sv/{slug} URL plus the REST invoke fallback.
03
Drafts 404 on the public URL. Deploy the snippet, send a signed POST, and watch the last-50 log. Replay a successful or test invocation from the card without re-copying the vendor payload.
04
Tell the Snippet Engineer you need a Stripe, Slack, GitHub, or generic webhook. It writes the handler, calls expose_as_function, fixture-tests with test_function, and waits for you to deploy. It never sees the live secret.
Authentication
The default is a rotate-able secret. Cookie modes cannot use GET. Public requires a low audit and a confirmation you have to click.
Default. Callers send X-SnipVault-Secret or Authorization: Bearer. Compared with hash_equals. Settings saves cannot plant a weak secret — only Rotate can change it.
WordPress cookies, POST only. A GET to /sv/{slug} from a logged-in browser is rejected so the endpoint cannot be CSRF'd by an image tag or a prefetch.
Same cookie rule, plus a required capability on the Function card. That field is not reused from the snippet's page-load capability — inbound auth is its own decision.
Only when the security audit is low and you explicitly confirm. No silent public endpoints. High-risk PHP cannot be opened to the internet from this card.
Built for production
A webhook is executable PHP on the public internet. 1.3.2 treats that as a deploy target, not a textarea with a URL.
01
The runner verifies the snippet signature and refuses to include a disk file that does not match stored content. A tamper is a 403, not an execution.
02
If the snippet's risk level exceeds your site deploy ceiling, the function is blocked. Public mode additionally requires a low audit and a confirmation flag.
03
Default 60 requests per minute per slug per IP (max 600). Unauthenticated traffic is capped at 30/min. Payloads over 1 MB return 413. Timeouts clamp from 1 to 30 seconds.
04
Only successful and test invocations store a payload, and only those can be replayed. 401/403 bodies are dropped so an attacker cannot plant JSON and wait for Replay.
Capabilities
https://yoursite.com/sv/your-slug is the permalink. If rewrites have not flushed yet, the same runner is on /wp-json/snipvault/v1/functions/{slug}/invoke for GET and POST.
The file is included (not require_once) with a timeout and an output buffer. A second test or replay in the same request can run again. Fatals become a JSON 500, not a white screen.
Today's invocation count, error rate, number of enabled functions, and the slowest slug — enough to notice a webhook that started timing out after a plugin update.
Imported sidecar metadata cannot enable a function or plant a secret. New imports stay off until an admin enables them on that site.
Safe Mode and SNIPVAULT_DISABLE_PHP_SNIPPETS return 503. Unpublished snippets 404. The Function card is a no-op on CSS and JavaScript snippets.
expose_as_function and test_function are first-class agent tools. Drafts can be fixture-tested before publish. The live secret stays on the Function card.
FAQ
No. Register a real REST route when you need schemas, namespaces, and a public contract. Snippet Functions are for inbound webhooks and small signed endpoints that should live next to the rest of your snippet library — with HMAC, logs, and a toggle.
No. Cookie-authenticated modes (logged in, capability) are POST-only. A GET would let any logged-in browser invoke privileged PHP via CSRF. Secret-header and confirmed public functions may allow GET.
In the vendor's header settings, or in your caller's environment. Never in snippet source, never in GitHub sidecar metadata, and never in an agent transcript. Rotate it from the Function card if it leaked.
A $snipvault_function array: method, redacted headers, json, body, query, ip, slug, and snippet_id. Read that. Do not read raw $_POST for the payload — the runner already parsed the body.
The include is isolated with an error handler. Execution failures return JSON 500 and land in the invocation log. That is a failed webhook, not a site-wide white screen. Still treat checkout-adjacent PHP like a deploy.
It can copy the PHP and the slug metadata. It cannot enable the function or copy the secret. You turn it on per site after review — the same rule as not auto-publishing imported snippets.
More features
Get started
Snippet Functions ship in 1.3.2 on every plan. One-time purchase, lifetime updates.