API: Wall behavior
The wall is a single handler in front of a publisher's origin. It returns null (pass through) or a Response (block). This is the request → decision contract, identical across all six form factors.
The decision tree
text
request ──has X-MotherShy header?──
│ YES ──▶ strict parse ──▶ validate ──▶ verify (offline)
│ │ fail ──▶ 400
│ │ verify fail ──▶ 401 (or 402/403 for spend/audience)
│ │ audience ≠ site ──▶ 403
│ │ valid + scoped ──▶ PASS (null)
│
└── NO ──▶ gateMode?
│ 'all' ──▶ 402 authorization required
└ 'agents-only' ──▶ classify(User-Agent)
├── human / free-pass bot ──▶ PASS (null)
└── agent ──▶ priced? x402 challenge : 402 recruitStatus mapping
| Condition | Status | reason |
|---|---|---|
| Valid + scoped | pass (null) | — |
| Human / free-pass bot | pass (null) | — |
| Un-enrolled agent | 402 | authorization required |
| Identity, no capability | 402 | spend key required |
| Priced, unpaid agent | 402 | payment_required (with PAYMENT-REQUIRED header) |
| Oversized nonce | 400 | request nonce exceeds safe integer range |
| Malformed / bad encoding | 400 | parse/encoding error |
| Bad signature / tampered | 401 | invalid request signature, cert: not signed by root, … |
| Cross-site capability | 403 | audience does not match this site |
Response shape
json
{
"error": "authorization_required",
"reason": "spend key required",
"site_id": "example.com",
"suggestion": "This site is protected by MotherShy. Get a key for your agent at https://mothershy.com/access?site=example.com"
}Plus a X-MotherShy-Wall header carrying the reason, for branching without parsing JSON.
User-Agent classification
With gateMode: 'agents-only', the wall classifies by User-Agent:
- Humans (browsers) → pass.
- Free-pass bots (Googlebot, Bingbot, link-preview bots) → pass.
- AI crawlers (GPTBot, ClaudeBot, etc.) and script agents (
curl,wget, …) → gated.
The classifier is shared across all form factors, so every wall gates identical traffic.
Free-pass / gated examples
text
Mozilla/5.0 (…) Chrome/120.0 → pass (human)
Mozilla/5.0 (compatible; Googlebot/2.1; +…) → pass (search)
Mozilla/5.0 (compatible; GPTBot/1.0) → 402 (AI crawler)
curl/8.0.1 → 402 (script)