Install
openclaw skills install rizzformsCreate forms, configure webhook delivery, manage submissions, and generate embed HTML using the RizzForms API and bundled CLI. Use this skill whenever the user asks to add a contact form, feedback form, signup form, lead capture form, waitlist form, or any form that collects submissions and delivers them via webhook. Also use when the user mentions RizzForms, wants to check form submissions, manage webhooks, or integrate a form backend into their site — even if they don't say "form backend" explicitly.
openclaw skills install rizzformsCreate forms that collect submissions and deliver them via webhook — no server code required. RizzForms handles storage, spam filtering, and delivery.
This skill includes a CLI at scripts/rizzforms. Use it instead of writing raw
curl commands — it handles authentication, pretty-prints JSON, and has commands
for every API operation.
# Make sure it's executable
chmod +x <skill-path>/scripts/rizzforms
# Set the API key (or run `rizzforms config` interactively)
export RIZZFORMS_API_KEY="frk_..."
# Now use it
<skill-path>/scripts/rizzforms forms
<skill-path>/scripts/rizzforms forms:create "Contact Form"
Run <skill-path>/scripts/rizzforms help for the full command list.
You need a RizzForms API key with the admin role (prefix frk_).
Check for an API key: Look for RIZZFORMS_API_KEY in the environment or
~/.config/rizzforms/config.
If no API key exists:
export RIZZFORMS_API_KEY="frk_..."RizzForms uses two subdomains — using the wrong one is a common mistake:
| Subdomain | Purpose |
|---|---|
forms.rizzness.com | Form submissions only (/f/ and /json/ routes) |
www.rizzness.com | API, dashboard, docs (/api/ routes) |
HTML form action and JSON submission URLs use forms.rizzness.com.
API management calls use www.rizzness.com.
The CLI handles this automatically.
<skill-path>/scripts/rizzforms forms:create "Contact Form"
The response includes endpoint_token, submission_url, json_url,
embed_html, and examples with ready-to-use curl commands.
Save the endpoint_token — you need it for every subsequent step.
If the user wants submissions delivered to an external URL:
<skill-path>/scripts/rizzforms plugins:create <endpoint_token> "https://their-server.com/webhook"
Requirements:
signing_secret from the response — it's shown only onceThe webhook receives a JSON POST on each submission:
{
"id": 12345,
"created_at": "2026-03-22T12:00:00Z",
"form_id": "abc123",
"form_name": "Contact Form",
"ip": "203.0.113.42",
"user_agent": "Mozilla/5.0...",
"referrer": "https://yoursite.com/contact",
"data": {
"name": "Jane Doe",
"email": "jane@example.com",
"message": "Hello!"
}
}
Each webhook includes an X-RizzForms-Signature header (HMAC-SHA256 of the
body using the signing secret). See references/api.md for verification
examples in Ruby, Node.js, and Python.
<skill-path>/scripts/rizzforms test <endpoint_token>
This sends a test submission with ?test=true for synchronous delivery results.
You can also pass custom JSON:
<skill-path>/scripts/rizzforms test <endpoint_token> '{"name": "Test", "email": "test@example.com"}'
If the webhook returns non-2xx or times out, the delivery status will be
"failed" with an error message.
Use the embed_html from the form creation response, or build a custom form.
Always include the hidden honeypot field _hp for spam protection.
<form action="https://forms.rizzness.com/f/{endpoint_token}" method="POST">
<label for="name">Name</label>
<input type="text" id="name" name="name" required>
<label for="email">Email</label>
<input type="email" id="email" name="email" required>
<label for="message">Message</label>
<textarea id="message" name="message" required></textarea>
<!-- Honeypot — keep hidden, critical for spam protection -->
<input type="text" name="_hp" style="display:none" tabindex="-1" autocomplete="off">
<button type="submit">Send</button>
</form>
RizzForms captures ALL form fields — there is no fixed schema. Add phone, company, budget, file upload, radio buttons, checkboxes — whatever is needed.
Match the user's CSS framework:
class="block w-full rounded-md border...")class="form-control", class="mb-3")Place the HTML form in the appropriate location in the codebase. The form
action URL points to RizzForms — no server-side code is needed.
For server-side/AJAX submissions, POST JSON to
https://forms.rizzness.com/json/{endpoint_token} instead.
# List all forms
<skill-path>/scripts/rizzforms forms
# Show form details (includes submission count, spam rate, plugin status)
<skill-path>/scripts/rizzforms forms:show <token>
# Update a form
<skill-path>/scripts/rizzforms forms:update <token> --name "New Name"
<skill-path>/scripts/rizzforms forms:update <token> --redirect "https://site.com/thanks"
<skill-path>/scripts/rizzforms forms:update <token> --active false
# List/manage plugins
<skill-path>/scripts/rizzforms plugins <token>
<skill-path>/scripts/rizzforms plugins:delete <token> <plugin_id>
<skill-path>/scripts/rizzforms plugins:rotate <token> <plugin_id>
# Recent submissions (default: last 24h)
<skill-path>/scripts/rizzforms submissions
# Filter by form and time range
<skill-path>/scripts/rizzforms submissions --form <token> --range 7d
# Search submissions
<skill-path>/scripts/rizzforms submissions --search "jane@example.com"
# View a specific submission
<skill-path>/scripts/rizzforms submissions:show <id>
# View spam
<skill-path>/scripts/rizzforms spam --form <token>
RizzForms has three layers of spam protection:
_hp (or _gotcha) field. Bots fill it, submission gets marked as spam. Always include this in your HTML.These field names get automatic normalization (stored in special_normalized):
| Field | Normalization |
|---|---|
email | Whitespace trimmed |
firstName, lastName | Whitespace trimmed |
name | Auto-computed from firstName + lastName if both present |
tags | CSV string converted to array |
priority | Lowercased, validated: low/medium/high/urgent |
urgent | Coerced to boolean |
_optin | Coerced to boolean (marketing opt-in) |
All fields are always stored as-is in payload_json regardless of normalization.
All errors return {"ok": false, "error": "code", "message": "..."}.
| Status | Error | Meaning |
|---|---|---|
| 401 | invalid_api_key | API key missing, invalid, or expired |
| 403 | forbidden | Key lacks required permission |
| 404 | not_found | Form/plugin not found or wrong account |
| 404 | not_active | Form is deactivated — reactivate with --active true |
| 422 | unsupported_plugin | Only "webhook" type supported via API |
| 422 | invalid_config | Webhook URL invalid, not HTTPS, or private IP |
| 503 | service_unavailable | Temporary — retry shortly |
For complete endpoint details, webhook signing verification code, and framework
quick-starts (Next.js, Astro, Hugo), see references/api.md.