All features

Webhooks from a PHP snippet. Meet Snippet Functions.

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

listening

POST/sv/stripe-webhook

X-SnipVault-Secret••••••••••••••••

  1. Secret headerwaiting
  2. HMAC + file matchwaiting
  3. $snipvault_functionwaiting

Last invocations

  • POST20042msok
  • POST20038msok

New in v1.3.2

A URL you can give Stripe. A file you already review.

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

From snippet to signed endpoint.

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

    Write a PHP handler

    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

    Enable the Function card

    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

    Publish, then invoke

    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

    Or ask the agent

    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

Four ways in. None of them are 'hope'.

The default is a rotate-able secret. Cookie modes cannot use GET. Public requires a low audit and a confirmation you have to click.

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.

Logged-in users

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.

Capability

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.

Public

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

The runner refuses more than it accepts.

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

    HMAC and file match

    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

    Audit ceiling

    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

    Rate, size, and time

    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

    Replay is not a confused deputy

    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

What ships in the Function card.

  • Pretty URL and REST fallback

    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.

  • Isolated include

    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.

  • Dashboard telemetry

    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.

  • GitHub cannot arm production

    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 kill switch

    Safe Mode and SNIPVAULT_DISABLE_PHP_SNIPPETS return 503. Unpublished snippets 404. The Function card is a no-op on CSS and JavaScript snippets.

  • Engineer tools

    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

Questions

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.

Get started

Give vendors a URL. Keep the PHP in SnipVault.

Snippet Functions ship in 1.3.2 on every plan. One-time purchase, lifetime updates.