documentation

InputGate API docs

v1.0 · stable

Welcome to the InputGate API. This documentation covers everything you need to integrate AI-powered inbound filtering into your forms, emails, automations, webhooks, and AI workflows.

InputGate sits between your inbound traffic and your systems — analyzing content in real time, scoring risk, and returning structured results you can act on immediately. You send form fields as a flexible fields object, and InputGate produces a single combined score across all of them.

The InputGate API is REST-based, returns JSON, and uses standard HTTP status codes. No SDKs required — any HTTP client works out of the box.
Privacy by default. Submissions are scored and immediately discarded unless flagged as spam. We never train on customer data. See Privacy & GDPR for the full posture.

Base URL

BASE https://api.inputgate.cloud/v1

What you get back

Every request returns a concise JSON object. The score and recommendation are yours to act on — InputGate never blocks anything on your behalf.

spam_scoreinteger · 0–100
A composite AI score across all submitted fields. 0 = clean, 100 = definite spam. Use this to apply your own threshold logic.
is_spamboolean
InputGate's recommendation based on the score. true means we consider this spam — but the final decision is always yours.
user_reasonstring
Plain-English explanation of what triggered the score. Safe to log or display in admin dashboards.
quick start

Up in 5 minutes.

Get InputGate running with a single API call. No SDK, no configuration file, no complicated setup. If you can make an HTTP request, you're ready.

Step 1 — Get your API key

Sign up at inputgate.cloud, navigate to Settings → API keys, and generate your first key. Keep it secret — treat it like a password.

Never expose your API key in frontend code, public repositories, or client-side JavaScript. Always call InputGate from your server.

Step 2 — Send your first request

POST your form data to /v1/check. Use the fields object for all text inputs — include an email key inside it if the form has one. Pass client_ip and domain at the top level for best accuracy.

first-request
const response = await fetch("https://api.inputgate.cloud/v1/check", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${'{'}YOUR_API_KEY{'}'}`,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    fields: {
      email:   "user@example.com",
      name:    "Free Moneymaker",
      message: "Buy cheap meds online! Click here now!!!"
    },
    client_ip: "203.0.113.42",
    domain:    "myapp.com",
    retention: "flagged_only"
  })
});

const result = await response.json();
console.log(result);
import requests

response = requests.post(
    "https://api.inputgate.cloud/v1/check",
    headers={
        "Authorization": "Bearer YOUR_API_KEY",
        "Content-Type": "application/json"
    },
    json={
        "fields": {
            "email":   "user@example.com",
            "name":    "Free Moneymaker",
            "message": "Buy cheap meds online! Click here now!!!"
        },
        "client_ip": "203.0.113.42",
        "domain":    "myapp.com",
        "retention": "flagged_only"
    }
)

result = response.json()
print(result)
curl -X POST https://api.inputgate.cloud/v1/check \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": {
      "email":   "user@example.com",
      "name":    "Free Moneymaker",
      "message": "Buy cheap meds online! Click here now!!!"
    },
    "client_ip": "203.0.113.42",
    "domain":    "myapp.com",
    "retention": "flagged_only"
  }'
$response = file_get_contents('https://api.inputgate.cloud/v1/check', false,
  stream_context_create(['http' => [
    'method' => 'POST',
    'header' => "Authorization: Bearer YOUR_API_KEY\r\nContent-Type: application/json\r\n",
    'content' => json_encode([
      'fields' => [
        'email'   => 'user@example.com',
        'name'    => 'Free Moneymaker',
        'message' => 'Buy cheap meds online! Click here now!!!'
      ],
      'client_ip' => '203.0.113.42',
      'domain'    => 'myapp.com',
      'retention' => 'flagged_only'
    ])
  ]])
);

$result = json_decode($response, true);
var_dump($result);

Step 3 — Handle the response

200 OK application/json
{
  "spam_score":  94,
  "is_spam":     true,
  "user_reason": "Aggressive promotional language with urgency triggers",
  "latency_ms":  340,
  "request_id":  "ig_req_a1b2c3d4e5f6"
}
That's it. Use spam_score to apply your own threshold, or treat is_spam as InputGate's recommendation. The decision is always yours.
authentication

API authentication

InputGate uses Bearer token authentication. Include your API key in the Authorization header on every request.

header-format
Authorization: Bearer ig_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx

Key types

ig_live_…production
Live key — counts against your monthly quota. Use in production environments only.
If your API key is compromised, rotate it immediately from the dashboard. Old keys are invalidated instantly. All requests using the old key will return 401 Unauthorized.
rate limits

Rate limits

Quotas are counted per user account across all API keys, on a calendar-month basis. Exceeding the limit returns a 429 Too Many Requests response.

Limits by plan

PlanRequests / month
Starter200
Growth10,000
Scale200,000
MoreCustom
privacy & gdpr

Privacy by design

InputGate is built to be GDPR-friendly out of the box. The endpoint accepts personal data (form fields, IP address) only to perform spam analysis on your behalf — it is never used for any other purpose, never sold, never used to train models.

Privacy by default. If you don't pass a retention parameter, InputGate defaults to "flagged_only" — clean submissions are scored and immediately discarded, with only an anonymised metadata row kept for quota counting. This aligns with GDPR Article 25 (data protection by default).

What we store, and for how long

Field valuessubmitted text
Retained only if retention is "full", or "flagged_only" + the submission was flagged as spam. Auto-deleted after 30 days for Starter/Growth, or after your configured log_retention_days on Scale and above.
client_ipIPv4 / IPv6
Same retention rules as field values. Used at request time for geo-filtering and reputation checks (legitimate interest under Art. 6(1)(f)); not stored when retention: "none".
Quota rowmetadata only
Always written — contains request ID, domain, score, timestamp, and the retention setting used. Contains no submission content and no IP. Needed for billing accuracy.
user_reasonmodel output
Plain-English explanation generated by the spam model. Designed to be safe for admin dashboards — never contains verbatim user content.

How to handle sensitive forms

For forms collecting health data, government IDs, financial details, or any other special-category data under GDPR Art. 9, pass retention: "none". InputGate will analyse the submission in-memory and discard the fields and IP immediately — only the anonymised quota row remains.

zero-retention-request
{
  "fields":    { "message": "…sensitive content…" },
  "client_ip": "203.0.113.42",
  "domain":    "clinic.example.com",
  "retention": "none"      // fields + IP discarded immediately after scoring
}

Compliance posture

Data minimisation
We only ever see the fields you choose to send. Don't send fields you don't need scored — fields is yours to shape (Art. 5(1)(c)).
Storage limitation
Retained content is automatically deleted after 30 days (default) or your configured retention window — never kept indefinitely (Art. 5(1)(e)).
No model training
Customer submissions are never used to train, fine-tune, or evaluate our spam-detection models.
Data residency
Requests are processed on Cloudflare's global edge. Persistent storage (D1) is region-pinned — contact us if you require an EU-only deployment.
Right to erasure
Self-serve: POST /v1/erasure with body { "client_ip": "…" } purges every log row tied to that IP across all your API keys. Idempotent, returns the row count deleted — use it to fulfil Art. 17 end-user requests programmatically.
DPA & subprocessors
A standard Data Processing Agreement is available on request. Our only subprocessors are Cloudflare (hosting, edge compute, D1, R2) and IPinfo (GeoIP lookups on client_ip).
Questions about compliance, DPA requests, or sub-processor lists? Email privacy@inputgate.cloud.
api reference

Check content

The core endpoint. Pass any number of textual form fields as a fields object, and InputGate returns a single combined risk assessment across all of them in real time.

Text fields only. The fields object is designed for values from <input type="text"> and <textarea> elements. Radio button values, checkbox states, select options, and similar non-textual data carry no spam signal and can skew the score — leave them out.
POST /v1/check

Request parameters

ParameterTypeRequiredDescription
fields object required The textual content to analyze, as a flat key/value map. You pick the keys — they're just labels ("name", "message", "subject", etc.) — and the values are the strings the user typed.

Use it for free-text inputs only<input type="text"> and <textarea>. Radio, checkbox, select, and similar non-textual values carry no spam signal and can skew the score, so leave them out.

Tip: if your form has an email field, name the key email — InputGate recognizes it and adds domain-reputation analysis on top of the text check.

Limits: max 20 fields, 10,000 characters combined.
client_ip string required The IP address of the person submitting the form — i.e. their browser's IP as seen by your server. Do not pass your own server IP, a Cloudflare IP, or any proxy address. This is checked against multiple spam and abuse denylists and is essential for geo-filtering features.
domain string required The domain of your application or website (e.g. "myapp.com"). Used to scope your logs, identify your integration in the dashboard, and improve model accuracy over time.
source string optional A label for your own tracking (e.g. "contact_form", "signup", "support"). Returned in logs and visible in your dashboard breakdowns.
retention string optional Controls whether the private content of the submission — the values inside fields and the client_ip — is retained in your dashboard logs. The request itself is always counted toward your monthly quota regardless of this setting.

  • "full" — retain fields and IP for every request.
  • "flagged_only" — retain fields and IP only when the submission is flagged as spam (needed for review). Clean submissions store metadata only.
  • "none" — never retain fields or IP. Only an anonymised quota-counting row is stored.
Default: "flagged_only" — privacy-by-default per GDPR Art. 25.
needLanguages array optional Require that the submission contains at least one of the specified languages. Pass language codes: "en" (ASCII Latin only), "latin" (any Latin-script language), "ru", "ar", "he", "zh", "ja", "ko", "ka". Other languages in the content are still allowed — the check is presence, not exclusivity. Content shorter than 3 characters skips this check.
blockedLanguages array optional Block submissions that contain any of the specified languages. Uses the same language codes as needLanguages. Evaluated before needLanguages.
allowedCountries array optional Accept submissions only from specific countries. Pass an array of two-letter ISO 3166-1 alpha-2 codes (e.g. ["US", "GB", "DE"]). Requires client_ip. If a country appears in both allowedCountries and blockedCountries, it is ignored by both rules.
blockedCountries array optional Block submissions from specific countries. Pass an array of two-letter ISO 3166-1 alpha-2 codes (e.g. ["RU", "KP"]). Requires client_ip.
Privacy & GDPR. Send retention: "none" for forms that handle sensitive personal data — InputGate will analyse the submission in-memory and discard the values and IP immediately, retaining only an anonymised quota row. The default "flagged_only" already keeps clean submissions content-free; only flagged spam is retained for review purposes (legitimate interest under GDPR Art. 6(1)(f)).

Full example

POST /v1/check
const response = await fetch("https://api.inputgate.cloud/v1/check", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${'{'}process.env.INPUTGATE_API_KEY{'}'}`,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    fields: {
      email:   req.body.email,
      name:    req.body.name,
      message: req.body.message
    },
    client_ip:        req.ip,
    domain:           "myapp.com",
    source:           "contact_form",
    retention:        "flagged_only",
    needLanguages:    ["en"],
    blockedLanguages: ["ru", "ar"],
    allowedCountries: ["US", "GB", "CA"]
  })
});

const { is_spam, spam_score, user_reason } = await response.json();
if (spam_score > 75) {
  return res.status(400).json({ error: "Submission blocked." });
}
import requests, os

res = requests.post(
    "https://api.inputgate.cloud/v1/check",
    headers={
        "Authorization": f"Bearer {os.environ['INPUTGATE_API_KEY']}",
        "Content-Type": "application/json"
    },
    json={
        "fields": {
            "email":   form_data["email"],
            "message": form_data["message"]
        },
        "client_ip":        request.remote_addr,
        "domain":           "myapp.com",
        "source":           "contact_form",
        "retention":        "flagged_only",
        "needLanguages":    ["en"],
        "blockedLanguages": ["ru", "ar"],
        "allowedCountries": ["US", "GB", "CA"]
    }
).json()

if res["spam_score"] > 75:
    raise ValueError("Submission blocked")
curl -X POST https://api.inputgate.cloud/v1/check \
  -H "Authorization: Bearer $INPUTGATE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": {
      "email":   "jane@example.com",
      "message": "Hello, I am interested in your services."
    },
    "client_ip":        "203.0.113.42",
    "domain":           "myapp.com",
    "source":           "contact_form",
    "retention":        "flagged_only",
    "needLanguages":    ["en"],
    "blockedLanguages": ["ru", "ar"],
    "allowedCountries": ["US", "GB", "CA"]
  }'
$payload = json_encode([
  'fields' => [
    'email'   => $_POST['email'],
    'message' => $_POST['message']
  ],
  'client_ip'        => $_SERVER['REMOTE_ADDR'],
  'domain'           => 'myapp.com',
  'source'           => 'contact_form',
  'retention'        => 'flagged_only',
  'needLanguages'    => ['en'],
  'blockedLanguages' => ['ru', 'ar'],
  'allowedCountries' => ['US', 'GB', 'CA']
]);

$ctx = stream_context_create(['http' => [
  'method'  => 'POST',
  'header'  => "Authorization: Bearer " . getenv('INPUTGATE_API_KEY') . "\r\nContent-Type: application/json\r\n",
  'content' => $payload
]]);

$result = json_decode(file_get_contents('https://api.inputgate.cloud/v1/check', false, $ctx), true);

if ($result['spam_score'] > 75) {
  http_response_code(400);
  exit('Submission blocked.');
}
api reference

Erase data

Self-serve GDPR Art. 17 erasure. Deletes every log row tied to a given client_ip across all API keys under your account. Idempotent — returns the number of rows deleted plus an audit-trail entry.

POST /v1/erasure

Request parameters

ParameterTypeRequiredDescription
client_ip string required The IP whose log entries should be erased. IPv4 or IPv6. IPv6 addresses are canonicalised (RFC 5952) — 2001:0db8::0042 and 2001:db8::42 match the same rows.

Example

POST /v1/erasure
curl -X POST https://api.inputgate.cloud/v1/erasure \
  -H "Authorization: Bearer $INPUTGATE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"client_ip": "203.0.113.42"}'
200 OK application/json
{
  "deleted":    12,
  "client_ip":  "203.0.113.42",
  "request_id": "ig_req_8f9f39db48fe"
}
Every erasure call writes an audit entry to erasure_log with the request ID, IP, and row count — satisfying GDPR Art. 30 (records of processing).
response schema

Response fields

Every successful call returns a JSON object with the following fields. All fields are always present — no optional keys in the response.

You're in control. is_spam is InputGate's recommendation, not a hard block. You can ignore it entirely and apply your own threshold logic using spam_score directly.
spam_scoreinteger · 0–100
Composite AI score across all submitted fields. 0–29 = clean, 30–59 = low risk, 60–79 = suspicious, 80–100 = likely spam.
is_spamboolean
InputGate's recommendation. true means we consider this submission spam — but you can override this at any time based on your own spam_score threshold.
user_reasonstring
Plain-English explanation of what drove the score. Safe to display in admin dashboards or internal logs. Never contains the original submitted content.
latency_msinteger
Processing time in milliseconds. Useful for monitoring and SLA tracking.
request_idstring · uuid
Unique ID for this check. Use when contacting support or cross-referencing entries in your logs.
errors

Error codes

InputGate uses standard HTTP status codes. Errors include a JSON body with error and message fields.

error-response-shape
{
  "error":      "invalid_api_key",
  "message":    "The API key provided is invalid or has been revoked.",
  "request_id": "ig_req_a1b2c3d4"
}
200
OK
Request succeeded. Check is_spam to determine if the content was flagged.
400
Bad request
Missing or invalid parameters. Check that fields, client_ip, and domain are present and correctly formatted.
401
Unauthorized
Missing, invalid, or revoked API key. Check your Authorization header format.
403
Forbidden
Your plan does not have access to this feature. Check your current plan limits in the dashboard.
422
Unprocessable
Content could not be analyzed — e.g. binary data or an unsupported encoding was submitted.
429
Too many requests
Monthly quota exhausted. Upgrade your plan or wait until the next billing cycle.
500
Internal error
Something went wrong on our end. These are rare — check status.inputgate.cloud and retry with exponential backoff.
503
Service unavailable
InputGate is temporarily unavailable. Retry after the Retry-After interval.
guides

Use cases

InputGate fits anywhere inbound data enters your stack. Here are the most common integration patterns.

Contact forms
Call /v1/check on form submit. Block or flag before the lead enters your CRM.
AI agent input
Validate user prompts before they reach your LLM. Block prompt injection and abusive content.
Email pipelines
Route inbound emails through InputGate before triggering automations. Keep your queue clean.
Webhook payloads
Validate webhook data before it executes logic. Catch malformed or malicious payloads at the edge.
Make / Zapier / n8n
Use the HTTP module to add InputGate as a filter step in any automation — no code required.
CRM lead scoring
Use spam_score and user_reason to score leads before writing to Salesforce, HubSpot, or Pipedrive.
integrations

Platform integrations

InputGate works with any platform that can make an HTTP request. Below are step-by-step patterns for the most common tools.

Make (Integromat)

Add an HTTP → Make a request module between your trigger and your action. Set Method to POST, URL to https://api.inputgate.cloud/v1/check, and add your Authorization header. Map the content field from your trigger data. Use a Router module to branch on is_spam.

In Make, parse the JSON response with the Parse JSON module, then use is_spam in a Filter condition to stop the scenario if the content is spam.

Zapier

Use a Webhooks by Zapier → POST action step. Set the URL, add headers, and map your data fields. Then add a Filter step that only continues if is_spam equals false.

n8n

Use the HTTP Request node with Method POST and JSON body. Connect it to an IF node that checks {{ $json["is_spam"] }}. Route the false branch to your downstream action.

Native InputGate nodes for Make, Zapier, and n8n are coming soon. Join the waitlist →
account

API keys & billing

Manage your API keys and billing from the InputGate dashboard at inputgate.cloud/dashboard.

Managing API keys

You can create multiple API keys — for example, one per environment (development, staging, production) or one per integration. Each key can be revoked independently without affecting others.

Monitoring usage

The dashboard shows real-time usage metrics: total requests, spam detection rate, top sources, and a timeline of checks. Use source parameter tagging to break down usage by integration point.

When you approach 90% of your monthly quota, InputGate sends an email alert. Once your monthly quota is exhausted, additional requests immediately return 429 Too Many Requests until the next billing cycle starts or you upgrade your plan.

Plans

PlanPriceRequests/moSupport
StarterFree200Community
Growth$19/mo10,000Email
Scale$99/mo200,000Email + SLA
MoreLet's talkCustomDedicated