InputGate API docs
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.
Base URL
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.
true means we consider this spam — but the final decision is always yours.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.
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. Add a short context string to calibrate the AI to your specific use case.
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", context: "Contact form on a B2B SaaS landing page", 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", "context": "Newsletter signup form for a cooking blog", "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", "context": "Job application form on a recruitment platform", "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', 'context' => 'User feedback form on a mobile productivity app', 'retention' => 'flagged_only' ]) ]]) ); $result = json_decode($response, true); var_dump($result);
Step 3 — Handle the response
{
"spam_score": 94,
"is_spam": true,
"user_reason": "Aggressive promotional language with urgency triggers",
"latency_ms": 340,
"request_id": "ig_req_a1b2c3d4e5f6"
}
spam_score to apply your own threshold, or treat is_spam as InputGate's recommendation. The decision is always yours.API authentication
InputGate uses Bearer token authentication. Include your API key in the Authorization header on every request.
Authorization: Bearer ig_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
Key types
401 Unauthorized.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
| Plan | Requests / month |
|---|---|
| Starter | 200 |
| Growth | 10,000 |
| Scale | 200,000 |
| More | Custom |
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.
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
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.retention: "none".retention setting used. Contains no submission content and no IP. Needed for billing accuracy.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.
{
"fields": { "message": "…sensitive content…" },
"client_ip": "203.0.113.42",
"domain": "clinic.example.com",
"retention": "none" // fields + IP discarded immediately after scoring
}
Compliance posture
fields is yours to shape (Art. 5(1)(c)).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.client_ip).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.
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.Request parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| 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. |
| context | string | optional |
A short plain-English description of the website, service, or form this request comes from — up to 100 characters. InputGate feeds this into the AI scoring engine to calibrate what "normal" looks like for your use case, improving accuracy without any training step on your end. Good examples: "Support ticket intake for an e-commerce store", "Contact form on a B2B SaaS landing page", "AI chatbot input on a healthcare platform".Tip: the more specific you are about your audience and typical content, the tighter the spam threshold becomes for your domain. Omitting it still works — the engine falls back to a generic baseline. |
| 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.
"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. |
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
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.'); }
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.
Request parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| 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
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"}'
{
"deleted": 12,
"client_ip": "203.0.113.42",
"request_id": "ig_req_8f9f39db48fe"
}
erasure_log with the request ID, IP, and row count — satisfying GDPR Art. 30 (records of processing).Response fields
Every successful call returns a JSON object with the following fields. All fields are always present — no optional keys in the response.
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.true means we consider this submission spam — but you can override this at any time based on your own spam_score threshold.Error codes
InputGate uses standard HTTP status codes. Errors include a JSON body with error and message fields.
{
"error": "invalid_api_key",
"message": "The API key provided is invalid or has been revoked.",
"request_id": "ig_req_a1b2c3d4"
}
is_spam to determine if the content was flagged.fields, client_ip, and domain are present and correctly formatted.Authorization header format.Retry-After interval.Use cases
InputGate fits anywhere inbound data enters your stack. Here are the most common integration patterns.
/v1/check on form submit. Block or flag before the lead enters your CRM.spam_score and user_reason to score leads before writing to Salesforce, HubSpot, or Pipedrive.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.
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.
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.
429 Too Many Requests until the next billing cycle starts or you upgrade your plan.Plans
| Plan | Price | Requests/mo | Support |
|---|---|---|---|
| Starter | Free | 200 | Community |
| Growth | $19/mo | 10,000 | |
| Scale | $99/mo | 200,000 | Email + SLA |
| More | Let's talk | Custom | Dedicated |