Access is invite-only during beta. Once invited, create a key to personalize these examples. Production sending requires a separate review.

Protect sign-ups with ShieldShiba

A free captcha that checks the email address and the browser.

ShieldShiba sits next to the email field on a sign-up or contact form. When a visitor types an address, the widget runs a short proof-of-work in the browser and checks the email, the IP, and the browser. There is no puzzle. A visitor who passes sees "Good human" and the form gets a token. Your server sends that token to PostShiba before it accepts the sign-up.

The token is bound to the email the visitor typed, so a solved check cannot be reused for a different address. Blocked visitors never see why they were blocked. Only your server sees the reasons.

We store the email's domain and a SHA-256 hash of the address, never the address itself. We also keep the IP, the user agent, and the verdict.

Create a site key

In your PostShiba account, open Security, then ShieldShiba. Create a site and list the hostnames that will embed the widget. Subdomains of a listed hostname are allowed.

Each site has two keys.

  • The site key starts with ss_pk_. It is public and goes in your HTML.
  • The secret key starts with ss_sk_. Keep it on your server. Rotate it from the same page if it leaks.

Two checks are per site. Data-center and hosting IPs are blocked by default, and you can turn that off. Free webmail is allowed by default. Turn that check on if your sign-ups should use a work address.

Embed the widget

Load the script once, then put a <shield-shiba> tag inside the form. Point email-field at the email input with a CSS selector.

signup.html
1 <script src="https://postshiba.com/shield/v1/widget.js" async></script>
2
3 <form action="/signup" method="post">
4 <input type="email" name="email" id="email">
5 <shield-shiba sitekey="ss_pk_..." email-field="#email"></shield-shiba>
6 <button>Sign up</button>
7 </form>

When the visitor passes, the widget adds a hidden input named shield_shiba_token to the form. A blocked visitor gets no token.

Verify on your server

Send the token, the email from the submitted form, and your secret key to the verify endpoint.

verify.sh
1 curl -sS \
2 --request POST \
3 --url "https://postshiba.com/shield/v1/verify" \
4 --header "Content-Type: application/json" \
5 --data '{
6 "secret": "ss_sk_...",
7 "token": "TOKEN_FROM_FORM",
8 "email": "jane@acme.com"
9 }'

A valid token returns 200.

verify-response.json
1 {
2 "success": true,
3 "verdict": "good_boy",
4 "reasons": [],
5 "email": "jane@acme.com",
6 "hostname": "acme.com",
7 "created_at": "2026-09-23T05:12:44Z"
8 }

Accept the sign-up only when success is true and verdict is good_boy. Blocked visitors never get a token, so a successful verify always returns good_boy. You'll see bad_dog checks, with their reasons, in the account. hostname is the page the widget ran on. email is normalized.

Each token is single-use and valid for 5 minutes. The email you send must match the address the visitor typed when they solved the check.

Status Body Meaning
401 {"success": false, "error": "invalid_secret"} The secret key does not belong to the token's site.
422 {"success": false, "error": "invalid_token"} The token is missing, unknown, already used, expired, or bound to a different email.

Treat any error as a failed check. Ask the visitor to try again.

Reasons

reasons lists every check that flagged the visitor.

Reason Meaning
invalid_email The address is not well formed.
no_mx The domain has no mail server.
temp_email The domain is a disposable or temporary inbox.
sfs_domain The domain is on the StopForumSpam blocklist.
free_email The domain is free webmail. Only when the site has the free-webmail check on.
network_bounced The address hard-bounced or complained with more than one PostShiba sender.
machine_agent The browser looks scripted: headless, curl, webdriver, or a form filled too fast.
sfs_ip The IP is on the StopForumSpam blocklist.
abuseipdb_listed The IP has abuse reports on AbuseIPDB.
tor The IP is a Tor exit node.
hosting_ip The IP belongs to a data center or hosting provider. Only when the site blocks hosting IPs.

Check the token in Rails

Read the token from the form params and call verify before you create the user.

app/controllers/registrations_controller.rb
1 require "net/http"
2
3 class RegistrationsController < ApplicationController
4 SHIELD_VERIFY_URL = URI("https://postshiba.com/shield/v1/verify")
5
6 def create
7 email = params.require(:email)
8 unless shield_passed?(email, params[:shield_shiba_token])
9 flash.now[:alert] = "Please try again."
10 return render :new, status: :unprocessable_entity
11 end
12
13 User.create!(email: email)
14 redirect_to root_path
15 end
16
17 private
18
19 def shield_passed?(email, token)
20 return false if token.blank?
21
22 response = Net::HTTP.post(
23 SHIELD_VERIFY_URL,
24 {secret: ENV.fetch("SHIELD_SHIBA_SECRET"), token: token, email: email}.to_json,
25 "Content-Type" => "application/json"
26 )
27 body = JSON.parse(response.body)
28 response.is_a?(Net::HTTPOK) && body["success"] && body["verdict"] == "good_boy"
29 rescue JSON::ParserError, Net::OpenTimeout, Net::ReadTimeout
30 false
31 end
32 end

Log reasons on a failure if you want to see why a sign-up was blocked. Do not show them to the visitor.

About

PostShiba is the email platform that powers Bento behind the scenes. You can build your own products, like Bento, on top of it.

© 2026 PostShiba by Backpack Internet Pty. Ltd. All rights reserved.

The same policies that govern Bento are applied to PostShiba Privacy | Terms | Security