Overview
What it does
Section titled “What it does”Public Actions receives approved public or authenticated integration submissions, validates their payload, passes them to a registered handler, and can send successful results to configured destinations. It is an integration-administrator feature: use it to define a controlled action boundary for a form, API client, or automation provider, not for ordinary page editing.
Create an action
Section titled “Create an action”Go to System → Public Actions. Create an action with a unique key, name, status, and registered handler. Scope it to a site when appropriate, then configure its success/failure message or redirect, Zapier/API availability, and payload schema.
- Use Active only after the handler and destinations are ready.
- Use Paused to temporarily stop an action without removing its configuration.
- Use Archived when it should no longer accept new submissions.
The runtime expects payload_schema.fields to be a structured list of field definitions with a key, type, and required flag. The current Payload schema key/value control is not a nested schema designer, so have an integrator seed or update that structure and test the resulting request validation. Actions without valid schema fields reject submissions by default; the allow_schemaless_payloads escape hatch must be enabled in configuration and then accepts at most 16 KB.
The handler can apply further validation and performs the actual operation. If its key is no longer registered, the package stores the submission as Failed and returns a generic unavailable response. Review configured redirect URLs too: an action-level success or failure URL can send a visitor off the current site.
Expose a public form safely
Section titled “Expose a public form safely”The built-in page at /actions/{key} is available only for an Active action whose settings.public_page_enabled value is true. That setting is not exposed by the current action form, so an integrator must set it deliberately. The page is noindex and no-store and renders only simple email, text, URL, and telephone inputs; use a package or site-owned form for richer schema types.
- Public form submissions are CSRF-protected and default to 12 attempts per minute for each action, email, and IP combination. Per-action limits can be supplied in package configuration or
settings.rate_limit.per_minute. - The default spam adapter is a honeypot, but the supplied public form does not render the configured
_hpfield. Add the honeypot field in the calling form or enable and render Turnstile, hCaptcha, or reCAPTCHA correctly. Every enabled adapter must pass; enabling a CAPTCHA without its secret and response token fails closed, including on non-trusted Form Builder or integration submissions. - The supplied page does not add a privacy notice or consent field. Put the required notice and consent capture in the calling form and schema for the data you collect.
- Form Builder connections are configuration-only: map a form handle or
id:{id}to an action underform_builder.mappings. The listener calls the handler synchronously and does not swallow action or validation failures, so test the mapped action before exposing the form. - A public client may send an
Idempotency-Keyheader oridempotency_keyfield. Reusing it for the same action returns the first stored result and payload without running the handler or destinations again. - Spam, schema, inactive-action, and throttle rejection happens before a submission record is created. Do not treat the Submissions ledger as a complete request or abuse log.
Add a destination
Section titled “Add a destination”Open Destinations under Public Actions and select the action it should receive. Set its name, status, adapter, endpoint URL, secret, headers, and adapter settings. Endpoint URLs, secrets, and headers are encrypted at rest; destination Settings are not, so never place credentials there. Administrators with edit access can reveal the decrypted endpoint and secret.
The built-in HTTP adapter requires HTTPS, blocks private and reserved addresses, pins the resolved address, and never follows redirects. An integrator can deliberately relax the HTTPS or private-address guards, but the package records a warning when either is relaxed. When a secret is set, it signs the exact JSON body with HMAC-SHA256 in X-Capell-Signature; the receiving system must verify that header. Keep the default POST method for sensitive payloads because GET puts the payload and metadata in the URL query string.
Delivery is asynchronous by default, on the configured Laravel queue. Keep a queue worker running. Setting sync to true sends during the submission request and does not get the queued job’s automatic retries. Pausing a destination prevents new successful submissions from creating attempts for it, but it does not cancel a job that is already queued.
Create and revoke integration tokens
Section titled “Create and revoke integration tokens”Open Integration Tokens and choose Create token. Give it a recognizable name, select the provider, choose the site scope, and grant only the abilities the integration needs. Global tokens are available only to global administrators; site-scoped users can create tokens for their permitted sites.
Copy the token from the creation notification immediately. The token list later shows its name, provider, last use, and revocation date, but not the plain secret. Revoke a token with confirmation as soon as the connected integration is no longer trusted or needed.
- A token can list actions, submit actions, and/or read submissions. Read submissions returns decrypted submission payloads, so grant it only when the integration needs that data.
- An action must be Active and have Zapier enabled or API enabled for the matching token provider. A site-scoped token sees only actions and submissions assigned directly to that site; it does not inherit global actions.
- The authenticated API defaults to 120 requests per minute per token. Provider- and token-specific limits are configuration, not action-form fields.
- The list does not display a token’s site or abilities after creation. Record the grant when issuing it and revoke and replace the token if its scope is uncertain.
Trusted inbound submissions use a separate endpoint and do not use integration tokens. Provision one or more encrypted trusted_submission_secrets on the action through an integration; there is no admin field for them. Package configuration also supports one fallback secret keyed by action. Prefer X-Capell-Signature containing HMAC-SHA256 of <X-Capell-Timestamp>.<raw body>; the timestamp accepts a five-minute clock window by default. A matching Bearer secret is also accepted. Every trusted request must include an idempotency key.
Monitor deliveries
Section titled “Monitor deliveries”- Submissions is a read-only ledger of received, handled, and failed handler processing. Handled means the handler succeeded; it does not mean every destination accepted the webhook.
- Dispatch Attempts is the separate delivery ledger. An asynchronous retryable response or connection failure is tried up to three times, using the configured backoff and jitter, and the same attempt row is updated in place. Errors caught by the HTTP adapter, such as an invalid endpoint, are marked Failed. An unregistered adapter fails before that update and can leave its durable row Pending, so check failed queue jobs when a pending row does not move.
- For a pending, retryable, or failed attempt, Replay performs one immediate delivery with the currently saved destination settings and creates a new attempt row. It is not queued for another automatic retry, and succeeded attempts cannot be replayed.
- The admin tables show statuses, source type, destination, HTTP status, and timestamps. They do not show decrypted submission payloads, metadata, response summaries, or error text.
Good to know
Section titled “Good to know”- Actions, destinations, submissions, attempts, and tokens use separate Shield permissions as well as site scope. A site assignment alone does not grant access, and only a global actor with token-create permission can issue a global token.
- Submission payloads are encrypted. Source identifiers, idempotency keys, status, timestamps, request URL, referrer, user agent, and keyed IP fingerprint metadata are stored separately; dispatch response/error summaries are plaintext after configured destination values are redacted. Design schemas to collect only what the handler and destinations need.
- When Privacy Center is installed, export and erasure match a subject by exact source type/id or by an exact email value under a payload key containing
email. Erasure deletes the matching submissions and attempts; it does not discover arbitrary personal data stored under other field names. capell:public-actions:prune-submissionsdefaults to submissions older than 365 days and deletes their dispatch attempts by cascade. Use--dry-runfirst. The package does not schedule this command, so add it to the host scheduler at the retention cadence your policy requires.- Diagnostics checks the storage tables, webhook adapter and presets, Form Builder bridge, SSRF safeguards, and whether schemaless payloads have been enabled. Treat a relaxed webhook or schemaless diagnostic as a production review item.
For developers: see the README.