Metering

Rate limit your AI endpoint by real abuse, not IP counts. FormShield Metering caps cost on LLM and public routes and catches multi-account abuse. Coming soon.

Rate-limit your AI endpoint by abuse, not IPs. Wrap any public or LLM-powered route, set a limit, and let FormShield catch multi-account abuse and cap the bill before it runs away.

The problem

A single abuser cycling IPs, keys, or throwaway accounts can blow past per-IP rate limits and run your token bill into the ground overnight. Naive rate limiting either throttles real users or misses the distributed abuse that actually costs you money on LLM-backed routes.

Metering targets that failure mode directly: it correlates the caller across IPs, sessions, and accounts to detect one actor wearing many hats — not just count requests per key.

When to use it

Reach for Metering in front of any resource where requests are expensive or abusable:

LLM endpoints

Chat completions, support-bot turns, and any token-metered route where a runaway loop or coordinated abuse drains your model spend.

Expensive public routes

A costly search, an export, or any unauthenticated endpoint where distributed abuse slips under a plain per-IP limit.

How it works

  1. Wrap the endpoint

    Call POST /v1/meter from in front of the resource you want to protect — a chat completion, a support-bot turn, an expensive search, any public route. Pass an identifier for the caller (user id, session, IP) and the limit you want to enforce.

  2. FormShield scores the request

    We correlate the caller across IPs, sessions, and accounts to detect one actor wearing many hats, not just count requests per key. You get back an allow / throttle / block decision plus the abuse signals behind it.

  3. Cap cost before it runs away

    Set a budget per identity or per window and FormShield enforces it at the decision boundary, so a runaway loop or a coordinated abuse campaign hits the cap instead of your invoice.

Quickstart

Call POST https://api.formshield.dev/v1/meter with your API key, the resource you’re protecting, an identity for the caller, and the limit to enforce. FormShield scores the request and returns the decision in the standard response envelope.

bash
curl https://api.formshield.dev/v1/meter \
  -H "Authorization: Bearer $FORMSHIELD_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "resource": "chat.completion",
    "identity": { "user_id": "u_4821", "ip": "203.0.113.42" },
    "limit": { "max": 100, "window": "1h" }
  }'

Response:

json
{
  "version": "1",
  "data": {
    "action": "throttle",
    "verdict": "multi_account_abuse",
    "confidence": 0.91,
    "usage": { "count": 138, "limit": 100, "window": "1h" },
    "linked_identities": 6
  },
  "error": null,
  "metadata": { "request_id": "req_9f2c1a", "processing_time_ms": 22 }
}

Here the same actor has been linked across six identities and is past the limit, so FormShield returns throttle — your code decides whether to serve, slow down, or reject.

Request body

resource string body required

A label for the route you’re protecting, e.g. chat.completion. Limits and usage are tracked per resource.

identity object body required

An identifier for the caller. Pass any of user_id, session, or ip — the more you supply, the better FormShield correlates one actor across IPs, sessions, and accounts.

limit object body required

The ceiling to enforce: max requests per window (e.g. 1h). Use this for a per-window cap, or set a credit budget to cap cost on LLM routes.

Response

action string

The decision: allow, throttle, or block. A clear action so you decide whether to serve, slow down, or reject — no opaque 429 with no reason attached.

verdict string

The reason behind the action, e.g. multi_account_abuse. Names the abuse signal so the decision is never a black box.

confidence float

How sure FormShield is of the verdict, from 0.0 to 1.0.

usage object

Current count against the limit for the window, so you can surface remaining headroom to the caller.

linked_identities integer

How many identities FormShield correlated to this caller — the count that turns one actor cycling fresh accounts or rotating IPs into a single subject.

Key signals

Multi-account abuse correlation

Links requests that share fingerprint, network, and behavioral signals so the same actor cycling fresh accounts or rotating IPs counts as one — the failure mode plain per-IP limits miss.

Cost caps for LLM endpoints

Enforce a credit or budget ceiling per identity and per window. The biggest win is a hard lid on token spend for chat and support bots before a single abuser drains it.

Allow / throttle / block decisions

Every call returns a clear action plus a verdict and confidence, so you decide whether to serve, slow down, or reject.

Distributed enforcement at the edge

Runs on the same edge path as the rest of FormShield, so the limit check adds little latency and works the same whether traffic hits one region or many.

Common questions

How do I rate limit an AI endpoint by real abuse instead of raw IP counts?

Coming soon: call POST /v1/meter in front of your LLM route with a caller identity and a limit. FormShield correlates the caller across IPs, sessions, and accounts and returns allow / throttle / block, so distributed abuse against a single endpoint is caught even when each IP looks under the limit. Join the early-access waitlist to try it on your endpoints.

When is Metering available and how do I get early access?

Metering is not live yet — it’s in development behind the POST /v1/meter endpoint. It’s the next FormShield surface after our live IP, email, content, and Voight products. Join the waitlist from the dashboard to get early access and help shape the limit and budget model.

How is Metering billed?

At launch, Metering will cost 2 credits per decision — each POST /v1/meter call that returns an allow / throttle / block verdict. Credits are the same shared balance used across FormShield, billed per service rather than per raw request, so you can mix Metering with your other checks on one plan.

Next steps

Type to search…

↑↓ navigate open esc close