# Integrating Spamadin Base URL: https://spamadin.com Schema: https://spamadin.com/openapi.json Human documentation: https://spamadin.com/docs Support: support@spamadin.com ## Authentication and website scope Send Authorization: Bearer YOUR_SPAMADIN_WEBSITE_KEY and Content-Type: application/json from your backend. Never expose the key in HTML, JavaScript, URLs, screenshots or logs. This is a Spamadin key, not an OpenRouter key. Create one account API key in the dashboard and reuse it across your websites. New hostnames are registered automatically within your plan limit through connection or check requests. example.com and www.example.com each use a website slot. Blocked websites remain blocked until explicitly allowed in the dashboard; reconnecting cannot bypass a block. Never let visitor input choose the hostname, API URL or credentials. Rotating or revoking the account key affects every integration using it; website records, blocks and history are preserved. Store the original message in your own system before requesting classification. The Spamadin service does not retain routine message bodies. Check metadata and keyed input digests last 30 days. Send only the text needed for classification; exclude passwords, payment details, files, and unrelated fields. ## Single check POST /api/v1/check Headers: Authorization, Content-Type, Idempotency-Key (a fresh UUID per original submission). JSON example: {"type":"contact","siteUrl":"https://example.com","content":"Could you send a quote for a new website?","context":{"title":"Website design quote request","language":"en"},"signals":{"elapsedMs":8500,"honeypotFilled":false}} type is contact or comment. content has 1–12000 characters; total JSON is at most 32768 bytes. Optional context accepts title (200 characters), description (1000), language (35), and up to 10 tags of 50 characters. Optional formId is the UUID of a saved website form profile. Do not invent profile IDs. reader_comment profiles require type comment; other profiles require contact. Unknown properties are rejected. Response fields: id (check UUID), verdict (allow/review/spam), score (0–100), reasons (string array), degraded (boolean), charged (boolean), policyVersion (string). The score is a decision score, not a calibrated probability. Persist the returned id locally for correction reports. It is distinct from the request Idempotency-Key. allow: continue your normal validation and delivery. spam: use your CMS spam queue or equivalent local handling. review or degraded: preserve for local moderation. No response, non-2xx, malformed response or unavailable service: preserve the submission and use a local fallback; never silently delete it. A verdict does not bypass other validation, authorization, or fraud controls. Retry transient failures with bounded exponential backoff, honoring Retry-After. Reuse the same UUID and unchanged payload. Completed retries within 30 days do not charge twice. Different payload with the same UUID is a conflict. Do not retry older checks. No automatic overages; usage is shared across the account and resets monthly even on annual plans. ## Bulk POST /api/v1/check/bulk {"checks":[{"id":"45573012-1f18-4eaf-97a1-29702376ea21","submission":{"type":"contact","siteUrl":"https://example.com","content":"Please send a quote."}}]} 1–20 items, distinct UUIDs within a batch, allowed to span websites in the account; website limits and blocks apply to every item. Total body at most 262144 bytes. Response: {"results":[{"id":"...","status":200,"result":{...decision...}}]}. Order is preserved. Check every item status; top-level success can contain item failures. Retry individual failed items with their same id and unchanged submission. Each completed non-degraded item consumes one check. ## Optional invisible evidence POST /api/v1/form-token from your server with {"siteUrl":"https://example.com","type":"contact"} and optional saved formId. Return only token, idempotencyKey, expiresAt and charged:false to your browser from your own same-origin endpoint. Never return the API key. Tokens expire after 30 minutes. Request when the visitor first interacts with the form to avoid unnecessary issuance. Use token in signals.formToken and its idempotencyKey as the submission UUID. Preserve this association through retries. Optional signals: elapsedMs (0–86400000), honeypotFilled (boolean), userAgent (512 characters), userIp (valid IPv4/IPv6), formToken (at most 1024 characters), browser. Never trust visitor-provided forwarding headers for IPs. Supply IP only when appropriate notices and lawful basis permit it. IPs support short-lived website-scoped burst evidence and are not sent to models; user agents do not affect classification. browser strict schema: version:1, jsExecuted:boolean; optional focusCount 0–1000, editCount 0–10000, pasteCount 0–1000, keyboardUsed:boolean, pointerUsed:boolean, firstInteractionMs 0–86400000. Counts only: never typed text, clipboard contents or pointer coordinates. Missing JavaScript, quick submission, paste, autofill or accessibility tools alone do not establish spam. Evidence is optional, not an authentication mechanism. ## Two correction reports — no content sharing required POST /api/v1/reports/false-positive with {"id":"RETURNED_CHECK_UUID"} for a real message incorrectly classified as spam. POST /api/v1/reports/missed-spam with the same shape for spam incorrectly allowed. Use your account API key. The check must belong to your account and its website must still accept requests. Response {"received":true}. A completed check must still exist in the normal 30-day metadata window. Corrections send no original message and consume no spam-check allowance. Repeating the same report is safe; the latest label wins. Reports clear website fingerprint decisions and inform support investigation; they do not instantly train or fine-tune an AI model or create a blanket sender/domain allowlist. Compatible combined endpoint: POST /api/v1/feedback with {"id":"RETURNED_CHECK_UUID","label":"legitimate"} or label:"spam". Do not send both named and combined reports for the same correction. Support can investigate a website and reference ID without receiving the message body. ## Explicit opt-in improvement examples Only if you have authority and deliberately choose to share content, POST /api/v1/training: {"checkId":"RETURNED_CHECK_UUID","label":"legitimate","submission":{"type":"contact","siteUrl":"https://example.com","content":"ORIGINAL_CHECK_TEXT"},"consent":{"authorizedToShare":true,"useForSpamImprovement":true}} Send the original submission fields unchanged; the service verifies a match. Both acknowledgments must be true. The completed check must be less than 30 days old. Sharing is optional, separate from metadata-only reports, and not immediate model training. Minimized encrypted examples expire after 90 days. Redaction is best-effort, not anonymization. Limits: 500 examples/2 MiB encrypted payload per account, 16 KiB original text, 24 KiB minimized payload, 32 KiB request, 2 GB global encrypted storage. No attachments. A full account returns 429; unavailable platform capacity/encryption returns 503. Do not retry indefinitely. GET /api/v1/training lists owned account example references; ?after=EXAMPLE_UUID paginates and ?id=EXAMPLE_UUID retrieves a minimized example. DELETE /api/v1/training with {"id":"EXAMPLE_UUID"} withdraws it. Dashboard deletion remains available after the account key is revoked. ## WordPress Download https://spamadin.com/downloads/spamadin.zip, install and activate. Create your account API key in the Spamadin dashboard and paste it in Settings → Spamadin. Use this same key on every WordPress website. Connection registers the configured hostname within plan limits; it does not issue a new key. The plugin encrypts the supplied account key locally. Reconnecting is safe and cannot unblock a blocked website. Comments and compatible contact forms are enabled by default. Comments remain in native WordPress moderation/spam queues. Held form messages stay privately in WordPress, capped at 500 records and 30 days; no emails, payments or form actions are replayed. Corrections send metadata only. Blocking the website in the dashboard stops its requests and frees its slot; disconnecting the plugin only stops local checks. ## Error handling 400 malformed/invalid input; 401 unavailable credentials; 402 inactive subscription/allowance; 404 resource unavailable; 409 conflict; 413 oversized body; 415 incorrect content type; 429 rate/storage limit; 500/503 service failure. Errors have {"error":"..."}. Do not depend on exact error wording or expose keys/content in logs. The API authenticates and enforces ownership, quotas and site limits server-side. Schema-defined optional fields provide flexibility; arbitrary extra fields are rejected. Website allowances: Starter includes 1 enabled website, Growth includes 5, and every Scale volume includes unlimited websites. Scale has no website-count storage cap. Monthly check allowances remain shared account-wide; website blocks, authentication and rate limits always apply.