Developer documentation

JevShield API documentation

Add message checks to your forms, or connect your AI assistant through MCP. Your integration decides what happens next.

01

Getting started

From an API key to your first server-side check.

  1. 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. 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. 3

    Make a server-side check

    Send a message, inspect the decision, and start in observation mode before enforcing blocking.

    View endpoint
cURL · first check
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.

Base URLhttps://jevshield.com
02

Authentication

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.

Keep production API keys on your server or trusted machine. Never put keys in frontend code, public repositories, URLs, or chat messages. Our database stores the key hash, not a recoverable copy.

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 · verify key
curl --fail-with-body 'https://jevshield.com/api/v1/check' \
  -H "Authorization: Bearer $JEVSHIELD_API_KEY"

Manage your API key
03

API reference

Three endpoints for checks, quota, and action reporting.

Check 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.

Request parameters
FieldRequirementDescription and limits
textstringRequired: text or emailMessage content. At least text or email must contain non-whitespace content.10,000 UTF-16 code units
emailstringRequired: text or emailSender email supplied by your form. Its presence does not verify sender identity.320 UTF-16 code units
sender_namestringOptionalSender name supplied by your form. A legacy alias is also accepted.200 UTF-16 code units
business_contextstringOptionalDescribe the inquiries your business wants. Empty or omitted context uses the saved account context.1,000 UTF-16 code units
sitestringOptionalAn HTTP or HTTPS site URL. Logs retain only its hostname; invalid metadata is omitted.2,048 UTF-16 code units
form_idstringOptionalAn 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.

JSON · illustrative response
{
  "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
Response fields
FieldTypeMeaning
successbooleanA normal classification response was returned.
is_spamboolean: verdict === blockCompatibility flag that matches the blocking recommendation.
verdictallow | review | blockA recommendation. Review is uncertain and is not an automatic hold or rejection.
scorenumber: 0–1Spam score. A rules score is a heuristic estimate, not a calibrated probability.
reasonstringExplanation of the classification.
enginejev | rulesProvider failures can fall back to local rules while still consuming normal quota.
detected_category, categorystringDetected message category and its compatibility alias.
model, confidenceoptionalPresent on successful AI results; do not require these fields on a rules result.
execution_time_msnumberAPI processing duration, not complete form-to-email delivery time.
quota_remainingnumberAccount checks remaining after this reservation.
lead_scorenumber: 0–100Buyer-intent score, not evidence of a purchase or verified identity.
lead_intentsales_inquiry | partnership | support | general | spamRouting classification, not proof of a purchase or sender identity.
lead_reasonoptional stringExplanation of the buyer-intent recommendation.
is_high_intentbooleanHigh-intent signal that may trigger a configured webhook. It is not inferred solely from a score threshold.
recommended_actionbook_meeting | notify_sales | normal_inbox | blockRouting recommendation. Your integration decides how to act on it.
meeting_urloptional stringReturned only for a high-intent result with a configured booking URL. The API does not follow it.
check_id, report_tokenoptional stringsReturned when logging succeeds. Keep the report token private on your trusted machine or server.
logging_statussaved | unavailableLogging failure does not change the classification result.
Observe before blocking: call the check endpoint, record the verdict, continue your normal submission flow, then report the action your integration applied. Observation still processes content and consumes quota.

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 · report action
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"}'

Request parameters
FieldRequirementDescription and limits
check_idUUID stringRequiredUse the identifier returned by the check that your integration acted on.A valid UUID
report_tokenstringRequiredUse the private receipt returned by that check, with the same account key.64 lowercase hexadecimal characters
actionallowed | blocked | error_allowedRequiredThe action your integration actually applied, rather than the classification recommendation.One supported action value
reasonverdict | threshold | uncertain | service_error | observe | trusted_senderRequiredThe 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

JSON · example notification
{
  "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.

JavaScript · host success callback
// 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 settings
04

Code examples

Copy a server-side example in your preferred language.

cURL
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.

05

Reference clients

Dependency-free JavaScript and Python source clients.

JavaScript

Node.js 18+ or a server Fetch runtime.

Download source

Python

Python 3.9+ with the standard library.

Download source

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.

06

MCP server

Connect an MCP client to JevShield through a local stdio server.

JevShield MCP

Node.js 20+ · local stdio transport · bundled SDK

Download MCP server
  1. 1. Download jevshield-mcp.mjs to your computer or server.
  2. 2. Set JEVSHIELD_API_KEY privately, and use the absolute file path in your MCP client configuration.
  3. 3. Restart the client and confirm that the three JevShield tools are available.
JSON · MCP client configuration
{
  "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
Shell · start stdio server
# 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

Available MCP tools
ToolBehaviorQuota
check_messageClassify a message through your account. Can write a detection log and trigger configured lead webhooks.1 check per reserved request
get_quotaRead key validity, plan, and remaining quota.Does not consume detection quota
report_actionRecord an action that your integration already applied, using the check ID and report token.Does not consume detection quota
MCP does not bypass API limits. Approve message processing before calling check_message; it consumes account quota and can trigger your configured webhook. report_action records execution but does not send, block, or deliver a message. No check is retried automatically.

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 reference
07

Errors and limits

Handle failures explicitly and choose your receiver’s policy before going live.

API error reference
StatusMeaningWhat to do
400Invalid inputThe check or report body fails validation.POST check / reportCorrect the fields and size before sending a new request.
401Authentication requiredA key is missing. Key verification also uses this status for an invalid or inactive key.GET / POST check; POST reportSupply the key in a request header and verify it with the quota endpoint.
403Invalid or inactive keyA check or report key is not accepted.POST check / reportCheck the key on your server and replace it through your account if necessary.
404Report receipt unavailableThe receipt is missing, expired, belongs to another account, or conflicts with an earlier report.POST reportUse the original receipt within 10 minutes and report only the action actually performed.
413Request body too largeThe HTTP server rejects a body over 128 KiB before the API handler runs.HTTP serverUse the smaller documented check or report body limits.
429Quota or report limit reachedA check has exhausted its allowance, or reports exceeded 300 requests in a fixed 60-second account window.POST check / reportRead your allowance or wait for the report window. Do not blindly retry checks.
500Unexpected server errorThe HTTP server could not complete the request.HTTP serverHandle the failure in your integration; a check may already have reserved quota.
503Service unavailableVerification, detection or reporting could not complete.GET / POST check; POST reportApply your chosen fallback policy. A timeout or failure after reservation does not automatically refund quota.
A timeout can happen after quota is reserved. Retrying a check may consume another check or trigger another webhook. A service failure after reservation does not automatically restore quota; AI-provider failure can return a normal, quota-consuming rules result.

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 terms

WordPress 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.

HTML · optional browser helper
<form data-formshield> ... </form>
<script src="https://jevshield.com/shield.js" data-key="YOUR_API_KEY"></script>

API and billing guidance reviewed October 5, 2026.