Getting started
From an API key to your first server-side check.
- 1
Create your account
Sign in with Google or an email verification code. The Free plan includes 100 checks per UTC calendar month.
Create account - 2
Generate an API key
Open Dashboard → API key. Copy the key when it is shown, and save it in your server environment.
Go to API key - 3
Make a server-side check
Send a message, inspect the decision, and start in observation mode before enforcing blocking.
View endpoint
curl --fail-with-body 'https://jevshield.com/api/v1/check' \
-H 'Content-Type: application/json' \
-H "x-api-key: $JEVSHIELD_API_KEY" \
--data '{"text":"Can you quote a website redesign?","form_id":"contact"}'Set JEVSHIELD_API_KEY in your server environment before running this example. It makes a real check, consumes 1 check, and may trigger your configured lead webhook.
https://jevshield.comAuthentication
Use one private API key for server-side requests.
Send x-api-key: YOUR_API_KEY, or Authorization: Bearer YOUR_API_KEY. If both are present, x-api-key takes precedence. Account cookies are not API credentials.
Verify your key and quota
GET /api/v1/check returns valid, plan, quota, used, and remaining. It does not classify a message or use detection quota.
curl --fail-with-body 'https://jevshield.com/api/v1/check' \
-H "Authorization: Bearer $JEVSHIELD_API_KEY"API reference
Three endpoints for checks, quota, and action reporting.
/api/v1/checkCheck a messageGET/api/v1/checkVerify a key and view quotaPOST/api/v1/reportReport an executed actionCheck a message
Supply a nonempty text or email. Account business context is used when the request does not provide its own. Messages are processed even when text storage is off.
| Field | Requirement | Description and limits |
|---|---|---|
textstring | Required: text or email | Message content. At least text or email must contain non-whitespace content.10,000 UTF-16 code units |
emailstring | Required: text or email | Sender email supplied by your form. Its presence does not verify sender identity.320 UTF-16 code units |
sender_namestring | Optional | Sender name supplied by your form. A legacy alias is also accepted.200 UTF-16 code units |
business_contextstring | Optional | Describe the inquiries your business wants. Empty or omitted context uses the saved account context.1,000 UTF-16 code units |
sitestring | Optional | An HTTP or HTTPS site URL. Logs retain only its hostname; invalid metadata is omitted.2,048 UTF-16 code units |
form_idstring | Optional | An integration label using letters, numbers, underscores, colons or hyphens. Invalid metadata is omitted.80 characters |
The entire check body is limited to 16,000 UTF-16 code units. The report body is limited to 1,000. Send a JSON object with Content-Type: application/json.
Read the decision
An allow verdict is not proof of sender identity. Review means uncertain. Your receiver chooses whether to allow, hold, or reject; JevShield does not host an inbox or quarantine queue.
{
"success": true,
"verdict": "allow",
"score": 0.08,
"reason": "Example: a relevant project inquiry.",
"engine": "jev",
"execution_time_ms": 420,
"lead_score": 72,
"lead_intent": "sales_inquiry",
"is_high_intent": false,
"recommended_action": "normal_inbox",
"quota_remaining": 99,
"logging_status": "saved",
"check_id": "CHECK_UUID",
"report_token": "TOKEN_FROM_CHECK"
}Illustrative response only. Fields vary by engine and configuration; optional logging and routing fields may be absent.
Response field reference
| Field | Type | Meaning |
|---|---|---|
success | boolean | A normal classification response was returned. |
is_spam | boolean: verdict === block | Compatibility flag that matches the blocking recommendation. |
verdict | allow | review | block | A recommendation. Review is uncertain and is not an automatic hold or rejection. |
score | number: 0–1 | Spam score. A rules score is a heuristic estimate, not a calibrated probability. |
reason | string | Explanation of the classification. |
engine | jev | rules | Provider failures can fall back to local rules while still consuming normal quota. |
detected_category, category | string | Detected message category and its compatibility alias. |
model, confidence | optional | Present on successful AI results; do not require these fields on a rules result. |
execution_time_ms | number | API processing duration, not complete form-to-email delivery time. |
quota_remaining | number | Account checks remaining after this reservation. |
lead_score | number: 0–100 | Buyer-intent score, not evidence of a purchase or verified identity. |
lead_intent | sales_inquiry | partnership | support | general | spam | Routing classification, not proof of a purchase or sender identity. |
lead_reason | optional string | Explanation of the buyer-intent recommendation. |
is_high_intent | boolean | High-intent signal that may trigger a configured webhook. It is not inferred solely from a score threshold. |
recommended_action | book_meeting | notify_sales | normal_inbox | block | Routing recommendation. Your integration decides how to act on it. |
meeting_url | optional string | Returned only for a high-intent result with a configured booking URL. The API does not follow it. |
check_id, report_token | optional strings | Returned when logging succeeds. Keep the report token private on your trusted machine or server. |
logging_status | saved | unavailable | Logging failure does not change the classification result. |
Logs and action reports
Dashboard → Detection logs covers the last 7 days of authenticated checks. Public demo checks are excluded. Text storage is off by default and can be enabled in your account; logs do not hold, resend, or restore messages.
When logging succeeds, the check response includes check_id and report_token. Keep the receipt private on your server or trusted MCP client. After applying your decision, report what your integration actually did with the same API key.
curl --fail-with-body 'https://jevshield.com/api/v1/report' \
-H 'Content-Type: application/json' \
-H "x-api-key: $JEVSHIELD_API_KEY" \
--data '{"check_id":"CHECK_UUID","report_token":"TOKEN_FROM_CHECK","action":"allowed","reason":"observe"}'| Field | Requirement | Description and limits |
|---|---|---|
check_idUUID string | Required | Use the identifier returned by the check that your integration acted on.A valid UUID |
report_tokenstring | Required | Use the private receipt returned by that check, with the same account key.64 lowercase hexadecimal characters |
actionallowed | blocked | error_allowed | Required | The action your integration actually applied, rather than the classification recommendation.One supported action value |
reasonverdict | threshold | uncertain | service_error | observe | trusted_sender | Required | The policy that explains the executed action.One supported reason value |
Reports use no detection quota. Tokens expire after 10 minutes. Identical retries are accepted; conflicting actions are rejected. A missing or failed report appears as Not reported. An allowed action does not confirm email delivery.
Lead routing
Save business context, a notification destination and a public HTTPS booking page in Dashboard → Routing. Choose email to your verified account, Slack, Discord, Teams Workflows, or a custom webhook for Zapier, Make and other automations.
Classify the inquiry
Use the verdict and your form policy first. Review is not a reason to automatically block an uncertain customer.
Notify the team
High-intent results can notify the configured destinations. Contact details are included; message text is off by default.
Let the visitor book
After the host form confirms success, offer a booking button. A booking link is not a confirmed meeting.
Different messengers and calendars work together
Your team can use Slack while your visitor uses email and Outlook. Share a web booking page from Calendly, Cal.com, Google appointment schedules or Microsoft Bookings. Connect the calendars that determine your availability inside that service. It handles time zones, conflicts, invitations and changes according to its settings and plan.
For iCloud availability, verify the provider supports a new iCloud connection. Apple Calendar can also display a connected Google or Exchange account. An ICS download is an event snapshot, not a live availability check or a synchronized cancellation workflow.
Connect a team notification
- Slack: create an Incoming Webhook for a channel, select Slack, and paste its URL. Notifications use plain text without automatic mention parsing.
- Discord: create a channel webhook, select Discord, and paste its URL. JevShield requests confirmation and disables automatic user or role mentions.
- Teams: use Workflows with a webhook trigger and an Adaptive Card action. Select Teams Workflows and add a co-owner. Legacy Office 365 Connectors are not the recommended setup.
- Zapier or Make: use a Catch Hook or Custom Webhook, then map contact and intent fields to your CRM or messenger. Telegram requires an authorized bot and chat; WhatsApp requires its own business messaging setup and recipient permission.
Send sample notification tests your selected services without using detection quota. The latest attempt shows HTTP acceptance or failure. This is not a delivery or read receipt. There are no automatic retries; configure downstream deduplication with event_id when using automations.
Custom webhook payload
{
"event": "lead.high_intent",
"event_id": "example-event-id",
"lead_score": 92,
"lead_intent": "sales_inquiry",
"is_high_intent": true,
"recommended_action": "book_meeting",
"sender_name": "Example visitor",
"email": "[email protected]",
"site": "example.com",
"booking_url": "https://cal.com/your-team/intro",
"timestamp": "2026-10-05T12:00:00.000Z"
}Example values are illustrative. The message field is included only when enabled. Use a destination you control and explain AI processing and notification providers in your form privacy notice.
Show booking after confirmed form success
Server integrations receive meeting_url for eligible high-intent results. Render it as an optional HTTPS link on your success screen after your form handler confirms success. Keep the original confirmation visible. Do not redirect on a timer or treat a classifier response as email delivery.
The optional browser helper emits a submission_id with formshield:verified. Pass the matching ID back in formshield:submitted only from your form’s confirmed success callback. The helper then offers a booking link for an eligible result. A block, review, failed submission or stale callback must not open a booking page.
// Add this listener once to the form already used by your integration.
let checkedSubmission;
form.addEventListener('formshield:verified', (event) => {
checkedSubmission = event.detail.submission_id;
});
// Adapt your EXISTING AJAX submit handler; do not add a second submit listener.
async function yourExistingSubmitHandler(event) {
event.preventDefault();
const submission_id = checkedSubmission; // Capture before this request starts.
checkedSubmission = undefined; // Never carry an old check into a later request.
// Keep your actual delivery request and its success condition here.
const result = await sendYourExistingForm(new FormData(form));
if (result.confirmedSuccess && submission_id) {
form.dispatchEvent(new CustomEvent('formshield:submitted', {
detail: { submission_id } // This request's ID, never a later global value.
}));
}
}The WordPress plugin keeps the original form delivery flow and does not automatically display a booking button. Add the booking link in your form’s success action, or use a custom server integration. A Google Meet, Zoom or Teams meeting URL is selected by your booking service; both people join using its supported browser or app.
Open routing settingsCode examples
Copy a server-side example in your preferred language.
curl --fail-with-body 'https://jevshield.com/api/v1/check' \
-H 'Content-Type: application/json' \
-H "x-api-key: $JEVSHIELD_API_KEY" \
--data '{"text":"Can you quote a website redesign?","form_id":"contact"}'These examples make real API calls when you run them on your server. They do not enforce form blocking, deliver email, or automatically retry failed checks. Test your full submission flow before enabling enforcement.
Reference clients
Dependency-free JavaScript and Python source clients.
The clients expose check, status, and report with bounded timeouts and no automatic retries. Download the source into your server project; these are not published npm or PyPI packages.
MCP server
Connect an MCP client to JevShield through a local stdio server.
JevShield MCP
Node.js 20+ · local stdio transport · bundled SDK
- 1. Download jevshield-mcp.mjs to your computer or server.
- 2. Set JEVSHIELD_API_KEY privately, and use the absolute file path in your MCP client configuration.
- 3. Restart the client and confirm that the three JevShield tools are available.
{
"mcpServers": {
"jevshield": {
"command": "node",
"args": ["/absolute/path/jevshield-mcp.mjs"],
"env": { "JEVSHIELD_API_KEY": "YOUR_API_KEY" }
}
}
}Replace the file path and key placeholder locally. Keep the configuration private. Clients use different configuration locations; this example is for clients that support mcpServers with command, args, and env.
Run directly with your environment key
# Download the standalone server. Requires Node.js 20+.
curl --fail 'https://jevshield.com/mcp/jevshield-mcp.mjs' -o jevshield-mcp.mjs
# Set JEVSHIELD_API_KEY in your trusted process environment.
node /absolute/path/jevshield-mcp.mjs| Tool | Behavior | Quota |
|---|---|---|
check_message | Classify a message through your account. Can write a detection log and trigger configured lead webhooks. | 1 check per reserved request |
get_quota | Read key validity, plan, and remaining quota. | Does not consume detection quota |
report_action | Record an action that your integration already applied, using the check ID and report token. | Does not consume detection quota |
MCP tool results can include a short-lived report_token. Your trusted AI host and its conversation history may retain this receipt. It still requires the same account key and expires after 10 minutes.
MCP setup and tool referenceErrors and limits
Handle failures explicitly and choose your receiver’s policy before going live.
| Status | Meaning | What to do |
|---|---|---|
| 400 | Invalid inputThe check or report body fails validation.POST check / report | Correct the fields and size before sending a new request. |
| 401 | Authentication requiredA key is missing. Key verification also uses this status for an invalid or inactive key.GET / POST check; POST report | Supply the key in a request header and verify it with the quota endpoint. |
| 403 | Invalid or inactive keyA check or report key is not accepted.POST check / report | Check the key on your server and replace it through your account if necessary. |
| 404 | Report receipt unavailableThe receipt is missing, expired, belongs to another account, or conflicts with an earlier report.POST report | Use the original receipt within 10 minutes and report only the action actually performed. |
| 413 | Request body too largeThe HTTP server rejects a body over 128 KiB before the API handler runs.HTTP server | Use the smaller documented check or report body limits. |
| 429 | Quota or report limit reachedA check has exhausted its allowance, or reports exceeded 300 requests in a fixed 60-second account window.POST check / report | Read your allowance or wait for the report window. Do not blindly retry checks. |
| 500 | Unexpected server errorThe HTTP server could not complete the request.HTTP server | Handle the failure in your integration; a check may already have reserved quota. |
| 503 | Service unavailableVerification, detection or reporting could not complete.GET / POST check; POST report | Apply your chosen fallback policy. A timeout or failure after reservation does not automatically refund quota. |
Monthly plans and quota
Free
$0/ month
100 checks
Starter
$9/ month
5,000 checks
Pro
$29/ month
25,000 checks
Agency
$69/ month
100,000 checks
Free quota resets each UTC calendar month; paid quota follows the subscription period. Unused checks do not roll over. Paid plans are monthly subscriptions with no automatic overage charges. Taxes and the final total are shown at checkout.
Each validated request that reserves quota uses 1 check, including allow, review, block, and rule fallback. Key verification and action reports do not use detection quota. Action reports are limited to 300 per account per minute.
See pricing and purchase termsWordPress integration
Install the JevShield plugin, then open Settings → JevShield AI. Enter your API key and the full HTTPS check endpoint. New installations start in Observe only; existing configured installations retain their mode until you change it.
The plugin reports its action automatically when a report token is available. Verify real form delivery before selecting Block high-confidence spam. Observation transmits submitted fields and uses quota; include this processing in your privacy notice.
WordPress.org releases may arrive later than the website ZIP. The legacy FormShield plugin keeps its existing settings and update path; its business-context and exact-email override settings are not included in the JevShield plugin.
Custom clients and edge access
The reference clients send an identifying User-Agent. If your custom server client gets Cloudflare 1010 or a non-JSON response, set an honest application User-Agent such as YourAppName/1.0 and inspect the status and content type. Test connectivity with a no-key GET /api/v1/check: JSON 401 is expected and uses no quota. Do not automatically retry POST checks after an uncertain result.
Optional browser helper
This helper is bypassable and exposes its API key to visitors. Use server-side checks for enforcement and key privacy. It checks only explicitly marked forms, and allows submission after network failure or a 6-second timeout. Test AJAX form plugins before enabling it.
<form data-formshield> ... </form>
<script src="https://jevshield.com/shield.js" data-key="YOUR_API_KEY"></script>